CMS 3D CMS Logo

List of all members | Public Member Functions | Private Member Functions | Private Attributes
MultiClusterAssociatorByEnergyScoreImpl Class Reference

#include <MultiClusterAssociatorByEnergyScoreImpl.h>

Inheritance diagram for MultiClusterAssociatorByEnergyScoreImpl:
hgcal::MultiClusterToCaloParticleAssociatorBaseImpl

Public Member Functions

hgcal::RecoToSimCollectionWithMultiClusters associateRecoToSim (const edm::Handle< reco::HGCalMultiClusterCollection > &mCCH, const edm::Handle< CaloParticleCollection > &cPCH) const override
 Associate a MultiCluster to CaloParticles. More...
 
hgcal::SimToRecoCollectionWithMultiClusters associateSimToReco (const edm::Handle< reco::HGCalMultiClusterCollection > &mCCH, const edm::Handle< CaloParticleCollection > &cPCH) const override
 Associate a CaloParticle to MultiClusters. More...
 
 MultiClusterAssociatorByEnergyScoreImpl (edm::EDProductGetter const &, bool, std::shared_ptr< hgcal::RecHitTools >, const std::unordered_map< DetId, const unsigned int > *&, std::vector< const HGCRecHit *> &hits)
 
- Public Member Functions inherited from hgcal::MultiClusterToCaloParticleAssociatorBaseImpl
 MultiClusterToCaloParticleAssociatorBaseImpl ()
 Constructor. More...
 
virtual ~MultiClusterToCaloParticleAssociatorBaseImpl ()
 Destructor. More...
 

Private Member Functions

hgcal::association makeConnections (const edm::Handle< reco::HGCalMultiClusterCollection > &mCCH, const edm::Handle< CaloParticleCollection > &cPCH) const
 

Private Attributes

const bool hardScatterOnly_
 
const std::unordered_map< DetId, const unsigned int > * hitMap_
 
std::vector< const HGCRecHit * > hits_
 
unsigned layers_
 
edm::EDProductGetter const * productGetter_
 
std::shared_ptr< hgcal::RecHitToolsrecHitTools_
 

Detailed Description

Definition at line 47 of file MultiClusterAssociatorByEnergyScoreImpl.h.

Constructor & Destructor Documentation

◆ MultiClusterAssociatorByEnergyScoreImpl()

MultiClusterAssociatorByEnergyScoreImpl::MultiClusterAssociatorByEnergyScoreImpl ( edm::EDProductGetter const &  productGetter,
bool  hardScatterOnly,
std::shared_ptr< hgcal::RecHitTools recHitTools,
const std::unordered_map< DetId, const unsigned int > *&  hitMap,
std::vector< const HGCRecHit *> &  hits 
)
explicit

Definition at line 13 of file MultiClusterAssociatorByEnergyScoreImpl.cc.

References layers_, and recHitTools_.

19  : hardScatterOnly_(hardScatterOnly),
20  recHitTools_(recHitTools),
21  hitMap_(hitMap),
22  hits_(hits),
24  layers_ = recHitTools_->lastLayerBH();
25 }
const std::unordered_map< DetId, const unsigned int > * hitMap_
EDProductGetter const * productGetter(std::atomic< void const *> const &iCache)

Member Function Documentation

◆ associateRecoToSim()

hgcal::RecoToSimCollectionWithMultiClusters MultiClusterAssociatorByEnergyScoreImpl::associateRecoToSim ( const edm::Handle< reco::HGCalMultiClusterCollection > &  cCH,
const edm::Handle< CaloParticleCollection > &  cPCH 
) const
overridevirtual

Associate a MultiCluster to CaloParticles.

Reimplemented from hgcal::MultiClusterToCaloParticleAssociatorBaseImpl.

Definition at line 499 of file MultiClusterAssociatorByEnergyScoreImpl.cc.

References edm::AssociationMap< Tag >::insert(), electronStore::links, LogDebug, makeConnections(), and productGetter_.

500  {
502  const auto& links = makeConnections(mCCH, cPCH);
503 
504  const auto& cpsInMultiCluster = std::get<0>(links);
505  for (size_t mcId = 0; mcId < cpsInMultiCluster.size(); ++mcId) {
506  for (auto& cpPair : cpsInMultiCluster[mcId]) {
507  LogDebug("MultiClusterAssociatorByEnergyScoreImpl")
508  << "multiCluster Id: \t" << mcId << "\t CP id: \t" << cpPair.first << "\t score \t" << cpPair.second << "\n";
509  // Fill AssociationMap
510  returnValue.insert(edm::Ref<reco::HGCalMultiClusterCollection>(mCCH, mcId), // Ref to MC
511  std::make_pair(edm::Ref<CaloParticleCollection>(cPCH, cpPair.first),
512  cpPair.second) // Pair <Ref to CP, score>
513  );
514  }
515  }
516  return returnValue;
517 }
hgcal::association makeConnections(const edm::Handle< reco::HGCalMultiClusterCollection > &mCCH, const edm::Handle< CaloParticleCollection > &cPCH) const
#define LogDebug(id)

◆ associateSimToReco()

hgcal::SimToRecoCollectionWithMultiClusters MultiClusterAssociatorByEnergyScoreImpl::associateSimToReco ( const edm::Handle< reco::HGCalMultiClusterCollection > &  cCH,
const edm::Handle< CaloParticleCollection > &  cPCH 
) const
overridevirtual

Associate a CaloParticle to MultiClusters.

Reimplemented from hgcal::MultiClusterToCaloParticleAssociatorBaseImpl.

Definition at line 519 of file MultiClusterAssociatorByEnergyScoreImpl.cc.

References edm::AssociationMap< Tag >::insert(), electronStore::links, makeConnections(), and productGetter_.

520  {
522  const auto& links = makeConnections(mCCH, cPCH);
523  const auto& cPOnLayer = std::get<1>(links);
524  for (size_t cpId = 0; cpId < cPOnLayer.size(); ++cpId) {
525  for (size_t layerId = 0; layerId < cPOnLayer[cpId].size(); ++layerId) {
526  for (auto& mcPair : cPOnLayer[cpId][layerId].multiClusterIdToEnergyAndScore) {
527  returnValue.insert(
528  edm::Ref<CaloParticleCollection>(cPCH, cpId), // Ref to CP
529  std::make_pair(edm::Ref<reco::HGCalMultiClusterCollection>(mCCH, mcPair.first), // Pair <Ref to MC,
530  std::make_pair(mcPair.second.first, mcPair.second.second)) // pair <energy, score> >
531  );
532  }
533  }
534  }
535  return returnValue;
536 }
hgcal::association makeConnections(const edm::Handle< reco::HGCalMultiClusterCollection > &mCCH, const edm::Handle< CaloParticleCollection > &cPCH) const

◆ makeConnections()

hgcal::association MultiClusterAssociatorByEnergyScoreImpl::makeConnections ( const edm::Handle< reco::HGCalMultiClusterCollection > &  mCCH,
const edm::Handle< CaloParticleCollection > &  cPCH 
) const
private

Definition at line 27 of file MultiClusterAssociatorByEnergyScoreImpl.cc.

References DummyCfis::c, caloTruthCellsProducer_cfi::caloParticles, CommonMethods::cp(), relativeConstraints::empty, mps_fire::end, hcalRecHitTable_cff::energy, f, spr::find(), cms::cuda::for(), newFWLiteAna::found, h, hitMap_, hits_, SimCluster::hits_and_fractions(), mps_fire::i, dqmiolumiharvest::j, dqmdumpme::last, layers_, LogDebug, CaloTowersParam_cfi::mc, SiStripPI::min, edm::Handle< T >::product(), recHitTools_, removeCPFromPU(), jetUpdater_cfi::sort, tier0::unique(), and findQualityFiles::v.

Referenced by associateRecoToSim(), and associateSimToReco().

28  {
29  // 1. Extract collections and filter CaloParticles, if required
30  const auto& mClusters = *mCCH.product();
31  const auto& caloParticles = *cPCH.product();
32  auto nMultiClusters = mClusters.size();
33  //Consider CaloParticles coming from the hard scatterer, excluding the PU contribution.
34  std::vector<size_t> cPIndices;
35  //Consider CaloParticles coming from the hard scatterer
36  //excluding the PU contribution and save the indices.
37  removeCPFromPU(caloParticles, cPIndices, false);
38  auto nCaloParticles = cPIndices.size();
39 
40  std::vector<size_t> cPSelectedIndices;
41  removeCPFromPU(caloParticles, cPSelectedIndices, true);
42 
43  //cPOnLayer[caloparticle][layer]
44  //This defines a "caloParticle on layer" concept. It is only filled in case
45  //that caloParticle has a reconstructed hit related via detid. So, a cPOnLayer[i][j] connects a
46  //specific caloParticle i in layer j with:
47  //1. the sum of all recHits energy times fraction of the relevant simHit in layer j related to that caloParticle i.
48  //2. the hits and fractions of that caloParticle i in layer j.
49  //3. the layer clusters with matched recHit id.
51  cPOnLayer.resize(nCaloParticles);
52  for (unsigned int i = 0; i < nCaloParticles; ++i) {
53  auto cpIndex = cPIndices[i];
54  cPOnLayer[cpIndex].resize(layers_ * 2);
55  for (unsigned int j = 0; j < layers_ * 2; ++j) {
56  cPOnLayer[cpIndex][j].caloParticleId = cpIndex;
57  cPOnLayer[cpIndex][j].energy = 0.f;
58  cPOnLayer[cpIndex][j].hits_and_fractions.clear();
59  }
60  }
61 
62  std::unordered_map<DetId, std::vector<hgcal::detIdInfoInCluster>> detIdToCaloParticleId_Map;
63  // Fill detIdToCaloParticleId_Map and update cPOnLayer
64  for (const auto& cpId : cPIndices) {
65  //take sim clusters
66  const SimClusterRefVector& simClusterRefVector = caloParticles[cpId].simClusters();
67  //loop through sim clusters
68  for (const auto& it_sc : simClusterRefVector) {
69  const SimCluster& simCluster = (*(it_sc));
70  const auto& hits_and_fractions = simCluster.hits_and_fractions();
71  for (const auto& it_haf : hits_and_fractions) {
72  const auto hitid = (it_haf.first);
73  const auto cpLayerId =
74  recHitTools_->getLayerWithOffset(hitid) + layers_ * ((recHitTools_->zside(hitid) + 1) >> 1) - 1;
75  const auto itcheck = hitMap_->find(hitid);
76  if (itcheck != hitMap_->end()) {
77  //Since the current hit from sim cluster has a reconstructed hit with the same detid,
78  //make a map that will connect a detid with:
79  //1. the caloParticles that have a simcluster with sim hits in that cell via caloParticle id.
80  //2. the sum of all simHits fractions that contributes to that detid.
81  //So, keep in mind that in case of multiple caloParticles contributing in the same cell
82  //the fraction is the sum over all caloParticles. So, something like:
83  //detid: (caloParticle 1, sum of hits fractions in that detid over all cp) , (caloParticle 2, sum of hits fractions in that detid over all cp), (caloParticle 3, sum of hits fractions in that detid over all cp) ...
84  auto hit_find_it = detIdToCaloParticleId_Map.find(hitid);
85  if (hit_find_it == detIdToCaloParticleId_Map.end()) {
86  detIdToCaloParticleId_Map[hitid] = std::vector<hgcal::detIdInfoInCluster>();
87  detIdToCaloParticleId_Map[hitid].emplace_back(cpId, it_haf.second);
88  } else {
89  auto findHitIt = std::find(detIdToCaloParticleId_Map[hitid].begin(),
90  detIdToCaloParticleId_Map[hitid].end(),
91  hgcal::detIdInfoInCluster{cpId, it_haf.second});
92  if (findHitIt != detIdToCaloParticleId_Map[hitid].end()) {
93  findHitIt->fraction += it_haf.second;
94  } else {
95  detIdToCaloParticleId_Map[hitid].emplace_back(cpId, it_haf.second);
96  }
97  }
98  const HGCRecHit* hit = hits_[itcheck->second];
99  //Since the current hit from sim cluster has a reconstructed hit with the same detid,
100  //fill the cPOnLayer[caloparticle][layer] object with energy (sum of all recHits energy times fraction
101  //of the relevant simHit) and keep the hit (detid and fraction) that contributed.
102  cPOnLayer[cpId][cpLayerId].energy += it_haf.second * hit->energy();
103  // We need to compress the hits and fractions in order to have a
104  // reasonable score between CP and LC. Imagine, for example, that a
105  // CP has detID X used by 2 SimClusters with different fractions. If
106  // a single LC uses X with fraction 1 and is compared to the 2
107  // contributions separately, it will be assigned a score != 0, which
108  // is wrong.
109  auto& haf = cPOnLayer[cpId][cpLayerId].hits_and_fractions;
110  auto found = std::find_if(
111  std::begin(haf), std::end(haf), [&hitid](const std::pair<DetId, float>& v) { return v.first == hitid; });
112  if (found != haf.end()) {
113  found->second += it_haf.second;
114  } else {
115  cPOnLayer[cpId][cpLayerId].hits_and_fractions.emplace_back(hitid, it_haf.second);
116  }
117  }
118  } // end of loop through simHits
119  } // end of loop through simclusters
120  } // end of loop through caloParticles
121 
122 #ifdef EDM_ML_DEBUG
123  LogDebug("MultiClusterAssociatorByEnergyScoreImpl") << "cPOnLayer INFO" << std::endl;
124  for (size_t cp = 0; cp < cPOnLayer.size(); ++cp) {
125  LogDebug("MultiClusterAssociatorByEnergyScoreImpl") << "For CaloParticle Idx: " << cp << " we have: " << std::endl;
126  for (size_t cpp = 0; cpp < cPOnLayer[cp].size(); ++cpp) {
127  LogDebug("MultiClusterAssociatorByEnergyScoreImpl") << " On Layer: " << cpp << " we have:" << std::endl;
128  LogDebug("MultiClusterAssociatorByEnergyScoreImpl")
129  << " CaloParticleIdx: " << cPOnLayer[cp][cpp].caloParticleId << std::endl;
130  LogDebug("MultiClusterAssociatorByEnergyScoreImpl")
131  << " Energy: " << cPOnLayer[cp][cpp].energy << std::endl;
132  double tot_energy = 0.;
133  for (auto const& haf : cPOnLayer[cp][cpp].hits_and_fractions) {
134  const HGCRecHit* hit = hits_[hitMap_->at(haf.first)];
135  LogDebug("MultiClusterAssociatorByEnergyScoreImpl")
136  << " Hits/fraction/energy: " << (uint32_t)haf.first << "/" << haf.second << "/"
137  << haf.second * hit->energy() << std::endl;
138  tot_energy += haf.second * hit->energy();
139  }
140  LogDebug("MultiClusterAssociatorByEnergyScoreImpl") << " Tot Sum haf: " << tot_energy << std::endl;
141  for (auto const& mc : cPOnLayer[cp][cpp].multiClusterIdToEnergyAndScore) {
142  LogDebug("MultiClusterAssociatorByEnergyScoreImpl") << " mcIdx/energy/score: " << mc.first << "/"
143  << mc.second.first << "/" << mc.second.second << std::endl;
144  }
145  }
146  }
147 
148  LogDebug("MultiClusterAssociatorByEnergyScoreImpl") << "detIdToCaloParticleId_Map INFO" << std::endl;
149  for (auto const& cp : detIdToCaloParticleId_Map) {
150  const HGCRecHit* hit = hits_[hitMap_->at(cp.first)];
151  LogDebug("MultiClusterAssociatorByEnergyScoreImpl")
152  << "For detId: " << (uint32_t)cp.first
153  << " we have found the following connections with CaloParticles:" << std::endl;
154  for (auto const& cpp : cp.second) {
155  LogDebug("MultiClusterAssociatorByEnergyScoreImpl")
156  << " CaloParticle Id: " << cpp.clusterId << " with fraction: " << cpp.fraction
157  << " and energy: " << cpp.fraction * hit->energy() << std::endl;
158  }
159  }
160 #endif
161 
162  // Fill detIdToMultiClusterId_Map and cpsInMultiCluster; update cPOnLayer
163  std::unordered_map<DetId, std::vector<hgcal::detIdInfoInMultiCluster>> detIdToMultiClusterId_Map;
164 
165  // this contains the ids of the caloParticles contributing with at least one hit to the multiCluster and the reconstruction error
166  //cpsInMultiCluster[multicluster][CPids]
167  //Connects a multiCluster with all related caloParticles.
168  hgcal::multiClusterToCaloParticle cpsInMultiCluster;
169  cpsInMultiCluster.resize(nMultiClusters);
170 
171  //Loop through multiClusters
172  for (unsigned int mcId = 0; mcId < nMultiClusters; ++mcId) {
173  const auto& hits_and_fractions = mClusters[mcId].hitsAndFractions();
174  if (!hits_and_fractions.empty()) {
175  std::unordered_map<unsigned, float> CPEnergyInMCL;
176  int maxCPId_byNumberOfHits = -1;
177  unsigned int maxCPNumberOfHitsInMCL = 0;
178  int maxCPId_byEnergy = -1;
179  float maxEnergySharedMCLandCP = 0.f;
180  float energyFractionOfMCLinCP = 0.f;
181  float energyFractionOfCPinMCL = 0.f;
182 
183  //In case of matched rechit-simhit, so matched
184  //caloparticle-layercluster-multicluster, we count and save the number of
185  //recHits related to the maximum energy CaloParticle out of all
186  //CaloParticles related to that layer cluster and multiCluster.
187 
188  std::unordered_map<unsigned, unsigned> occurrencesCPinMCL;
189  unsigned int numberOfNoiseHitsInMCL = 0;
190  unsigned int numberOfHitsInMCL = 0;
191 
192  //number of hits related to that cluster
193  unsigned int numberOfHitsInLC = hits_and_fractions.size();
194  numberOfHitsInMCL += numberOfHitsInLC;
195  std::unordered_map<unsigned, float> CPEnergyInLC;
196 
197  //hitsToCaloParticleId is a vector of ints, one for each recHit of the
198  //layer cluster under study. If negative, there is no simHit from any CaloParticle related.
199  //If positive, at least one CaloParticle has been found with matched simHit.
200  //In more detail:
201  // 1. hitsToCaloParticleId[hitId] = -3
202  // TN: These represent Halo Cells(N) that have not been
203  // assigned to any CaloParticle (hence the T).
204  // 2. hitsToCaloParticleId[hitId] = -2
205  // FN: There represent Halo Cells(N) that have been assigned
206  // to a CaloParticle (hence the F, since those should have not been marked as halo)
207  // 3. hitsToCaloParticleId[hitId] = -1
208  // FP: These represent Real Cells(P) that have not been
209  // assigned to any CaloParticle (hence the F, since these are fakes)
210  // 4. hitsToCaloParticleId[hitId] >= 0
211  // TP There represent Real Cells(P) that have been assigned
212  // to a CaloParticle (hence the T)
213 
214  std::vector<int> hitsToCaloParticleId(numberOfHitsInLC);
215  //det id of the first hit just to make the lcLayerId variable
216  //which maps the layers in -z: 0->51 and in +z: 52->103
217  const auto firstHitDetId = hits_and_fractions[0].first;
218  int lcLayerId = recHitTools_->getLayerWithOffset(firstHitDetId) +
219  layers_ * ((recHitTools_->zside(firstHitDetId) + 1) >> 1) - 1;
220 
221  //Loop though the hits of the layer cluster under study
222  for (unsigned int hitId = 0; hitId < numberOfHitsInLC; hitId++) {
223  const auto rh_detid = hits_and_fractions[hitId].first;
224  const auto rhFraction = hits_and_fractions[hitId].second;
225 
226  //Since the hit is belonging to the layer cluster, it must also be in the recHits map.
227  const auto itcheck = hitMap_->find(rh_detid);
228  const HGCRecHit* hit = hits_[itcheck->second];
229 
230  //Make a map that will connect a detid (that belongs to a recHit of the layer cluster under study,
231  //no need to save others) with:
232  //1. the layer clusters that have recHits in that detid
233  //2. the fraction of the recHit of each layer cluster that contributes to that detid.
234  //So, something like:
235  //detid: (layer cluster 1, hit fraction) , (layer cluster 2, hit fraction), (layer cluster 3, hit fraction) ...
236  //here comparing with the caloParticle map above
237  auto hit_find_in_LC = detIdToMultiClusterId_Map.find(rh_detid);
238  if (hit_find_in_LC == detIdToMultiClusterId_Map.end()) {
239  detIdToMultiClusterId_Map[rh_detid] = std::vector<hgcal::detIdInfoInMultiCluster>();
240  }
241  detIdToMultiClusterId_Map[rh_detid].emplace_back(hgcal::detIdInfoInMultiCluster{mcId, mcId, rhFraction});
242 
243  // Check whether the recHit of the layer cluster under study has a sim hit in the same cell
244  auto hit_find_in_CP = detIdToCaloParticleId_Map.find(rh_detid);
245 
246  // If the fraction is zero or the hit does not belong to any calo
247  // particle, set the caloParticleId for the hit to -1 and this will
248  // contribute to the number of noise hits
249  if (rhFraction == 0.) { // this could be a real hit that has been marked as halo
250  hitsToCaloParticleId[hitId] = -2;
251  }
252  if (hit_find_in_CP == detIdToCaloParticleId_Map.end()) {
253  hitsToCaloParticleId[hitId] -= 1;
254  } else {
255  auto maxCPEnergyInLC = 0.f;
256  auto maxCPId = -1;
257  for (auto& h : hit_find_in_CP->second) {
258  auto shared_fraction = std::min(rhFraction, h.fraction);
259  //We are in the case where there are caloParticles with simHits connected via detid with the recHit under study
260  //So, from all layers clusters, find the recHits that are connected with a caloParticle and save/calculate the
261  //energy of that caloParticle as the sum over all recHits of the recHits energy weighted
262  //by the caloParticle's fraction related to that recHit.
263  CPEnergyInMCL[h.clusterId] += shared_fraction * hit->energy();
264  //Same but for layer clusters for the cell association per layer
265  CPEnergyInLC[h.clusterId] += shared_fraction * hit->energy();
266  //Here cPOnLayer[caloparticle][layer] described above is set
267  //Here for multiClusters with matched recHit, the CP fraction times hit energy is added and saved
268  cPOnLayer[h.clusterId][lcLayerId].multiClusterIdToEnergyAndScore[mcId].first +=
269  shared_fraction * hit->energy();
270  cPOnLayer[h.clusterId][lcLayerId].multiClusterIdToEnergyAndScore[mcId].second = FLT_MAX;
271  //cpsInMultiCluster[multicluster][CPids]
272  //Connects a multiCluster with all related caloParticles
273  cpsInMultiCluster[mcId].emplace_back(h.clusterId, FLT_MAX);
274  //From all CaloParticles related to a layer cluster, we save id and energy of the caloParticle
275  //that after simhit-rechit matching in layer has the maximum energy.
276  if (shared_fraction > maxCPEnergyInLC) {
277  //energy is used only here. cpid is saved for multiClusters
278  maxCPEnergyInLC = CPEnergyInLC[h.clusterId];
279  maxCPId = h.clusterId;
280  }
281  }
282  //Keep in mind here maxCPId could be zero. So, below ask for negative not including zero to count noise.
283  hitsToCaloParticleId[hitId] = maxCPId;
284  }
285 
286  } //end of loop through recHits of the layer cluster.
287 
288  //Loop through all recHits to count how many of them are noise and how many are matched.
289  //In case of matched rechit-simhit, we count and save the number of recHits related to the maximum energy CaloParticle.
290  for (auto c : hitsToCaloParticleId) {
291  if (c < 0) {
292  numberOfNoiseHitsInMCL++;
293  } else {
294  occurrencesCPinMCL[c]++;
295  }
296  }
297 
298  //Below from all maximum energy CaloParticles, we save the one with the largest amount
299  //of related recHits.
300  for (auto& c : occurrencesCPinMCL) {
301  if (c.second > maxCPNumberOfHitsInMCL) {
302  maxCPId_byNumberOfHits = c.first;
303  maxCPNumberOfHitsInMCL = c.second;
304  }
305  }
306 
307  //Find the CaloParticle that has the maximum energy shared with the multiCluster under study.
308  for (auto& c : CPEnergyInMCL) {
309  if (c.second > maxEnergySharedMCLandCP) {
310  maxCPId_byEnergy = c.first;
311  maxEnergySharedMCLandCP = c.second;
312  }
313  }
314  //The energy of the CaloParticle that found to have the maximum energy shared with the multiCluster under study.
315  float totalCPEnergyFromLayerCP = 0.f;
316  if (maxCPId_byEnergy >= 0) {
317  //Loop through all layers
318  for (unsigned int j = 0; j < layers_ * 2; ++j) {
319  totalCPEnergyFromLayerCP = totalCPEnergyFromLayerCP + cPOnLayer[maxCPId_byEnergy][j].energy;
320  }
321  energyFractionOfCPinMCL = maxEnergySharedMCLandCP / totalCPEnergyFromLayerCP;
322  if (mClusters[mcId].energy() > 0.f) {
323  energyFractionOfMCLinCP = maxEnergySharedMCLandCP / mClusters[mcId].energy();
324  }
325  }
326 
327  LogDebug("MultiClusterAssociatorByEnergyScoreImpl") << std::setw(12) << "multiCluster"
328  << "\t" << std::setw(10) << "mulcl energy"
329  << "\t" << std::setw(5) << "nhits"
330  << "\t" << std::setw(12) << "noise hits"
331  << "\t" << std::setw(22) << "maxCPId_byNumberOfHits"
332  << "\t" << std::setw(8) << "nhitsCP"
333  << "\t" << std::setw(16) << "maxCPId_byEnergy"
334  << "\t" << std::setw(23) << "maxEnergySharedMCLandCP"
335  << "\t" << std::setw(22) << "totalCPEnergyFromAllLayerCP"
336  << "\t" << std::setw(22) << "energyFractionOfMCLinCP"
337  << "\t" << std::setw(25) << "energyFractionOfCPinMCL"
338  << "\t" << std::endl;
339  LogDebug("MultiClusterAssociatorByEnergyScoreImpl")
340  << std::setw(12) << mcId << "\t" << std::setw(10) << mClusters[mcId].energy() << "\t" << std::setw(5)
341  << numberOfHitsInMCL << "\t" << std::setw(12) << numberOfNoiseHitsInMCL << "\t" << std::setw(22)
342  << maxCPId_byNumberOfHits << "\t" << std::setw(8) << maxCPNumberOfHitsInMCL << "\t" << std::setw(16)
343  << maxCPId_byEnergy << "\t" << std::setw(23) << maxEnergySharedMCLandCP << "\t" << std::setw(22)
344  << totalCPEnergyFromLayerCP << "\t" << std::setw(22) << energyFractionOfMCLinCP << "\t" << std::setw(25)
345  << energyFractionOfCPinMCL << std::endl;
346  }
347  } // end of loop through multiClusters
348 
349  // Update cpsInMultiCluster; compute the score MultiCluster-to-CaloParticle,
350  // together with the returned AssociationMap
351  for (unsigned int mcId = 0; mcId < nMultiClusters; ++mcId) {
352  // find the unique caloParticles id contributing to the multilusters
353  std::sort(cpsInMultiCluster[mcId].begin(), cpsInMultiCluster[mcId].end());
354  auto last = std::unique(cpsInMultiCluster[mcId].begin(), cpsInMultiCluster[mcId].end());
355  cpsInMultiCluster[mcId].erase(last, cpsInMultiCluster[mcId].end());
356 
357  const auto& hits_and_fractions = mClusters[mcId].hitsAndFractions();
358  unsigned int numberOfHitsInLC = hits_and_fractions.size();
359  if (numberOfHitsInLC > 0) {
360  if (mClusters[mcId].energy() == 0. && !cpsInMultiCluster[mcId].empty()) {
361  //Loop through all CaloParticles contributing to multiCluster mcId.
362  for (auto& cpPair : cpsInMultiCluster[mcId]) {
363  //In case of a multiCluster with zero energy but related CaloParticles the score is set to 1.
364  cpPair.second = 1.;
365  LogDebug("MultiClusterAssociatorByEnergyScoreImpl")
366  << "multiClusterId : \t " << mcId << "\t CP id : \t" << cpPair.first << "\t score \t " << cpPair.second
367  << "\n";
368  }
369  continue;
370  }
371 
372  // Compute the correct normalization
373  float invMultiClusterEnergyWeight = 0.f;
374  for (auto const& haf : mClusters[mcId].hitsAndFractions()) {
375  const HGCRecHit* hit = hits_[hitMap_->at(haf.first)];
376  invMultiClusterEnergyWeight += (haf.second * hit->energy()) * (haf.second * hit->energy());
377  }
378  invMultiClusterEnergyWeight = 1.f / invMultiClusterEnergyWeight;
379 
380  for (unsigned int i = 0; i < numberOfHitsInLC; ++i) {
381  DetId rh_detid = hits_and_fractions[i].first;
382  float rhFraction = hits_and_fractions[i].second;
383 
384  bool hitWithNoCP = (detIdToCaloParticleId_Map.find(rh_detid) == detIdToCaloParticleId_Map.end());
385 
386  auto itcheck = hitMap_->find(rh_detid);
387  const HGCRecHit* hit = hits_[itcheck->second];
388  float hitEnergyWeight = hit->energy() * hit->energy();
389 
390  for (auto& cpPair : cpsInMultiCluster[mcId]) {
391  unsigned int multiClusterId = cpPair.first;
392  float cpFraction = 0.f;
393  if (!hitWithNoCP) {
394  auto findHitIt = std::find(detIdToCaloParticleId_Map[rh_detid].begin(),
395  detIdToCaloParticleId_Map[rh_detid].end(),
396  hgcal::detIdInfoInCluster{multiClusterId, 0.f});
397  if (findHitIt != detIdToCaloParticleId_Map[rh_detid].end())
398  cpFraction = findHitIt->fraction;
399  }
400  if (cpPair.second == FLT_MAX) {
401  cpPair.second = 0.f;
402  }
403  cpPair.second +=
404  (rhFraction - cpFraction) * (rhFraction - cpFraction) * hitEnergyWeight * invMultiClusterEnergyWeight;
405  }
406  } // End of loop over Hits within a MultiCluster
407 #ifdef EDM_ML_DEBUG
408  //In case of a multiCluster with some energy but none related CaloParticles print some info.
409  if (cpsInMultiCluster[mcId].empty())
410  LogDebug("MultiClusterAssociatorByEnergyScoreImpl") << "multiCluster Id: \t" << mcId << "\tCP id:\t-1 "
411  << "\t score \t-1"
412  << "\n";
413 #endif
414  }
415  } // End of loop over MultiClusters
416 
417  // Compute the CaloParticle-To-MultiCluster score
418  for (const auto& cpId : cPSelectedIndices) {
419  for (unsigned int layerId = 0; layerId < layers_ * 2; ++layerId) {
420  unsigned int CPNumberOfHits = cPOnLayer[cpId][layerId].hits_and_fractions.size();
421  if (CPNumberOfHits == 0)
422  continue;
423 #ifdef EDM_ML_DEBUG
424  int mcWithMaxEnergyInCP = -1;
425  float maxEnergyMCLperlayerinCP = 0.f;
426  float CPenergy = cPOnLayer[cpId][layerId].energy;
427  float CPEnergyFractionInMCLperlayer = 0.f;
428  for (auto& mc : cPOnLayer[cpId][layerId].multiClusterIdToEnergyAndScore) {
429  if (mc.second.first > maxEnergyMCLperlayerinCP) {
430  maxEnergyMCLperlayerinCP = mc.second.first;
431  mcWithMaxEnergyInCP = mc.first;
432  }
433  }
434  if (CPenergy > 0.f)
435  CPEnergyFractionInMCLperlayer = maxEnergyMCLperlayerinCP / CPenergy;
436 
437  LogDebug("MultiClusterAssociatorByEnergyScoreImpl")
438  << std::setw(8) << "LayerId:\t" << std::setw(12) << "caloparticle\t" << std::setw(15) << "cp total energy\t"
439  << std::setw(15) << "cpEnergyOnLayer\t" << std::setw(14) << "CPNhitsOnLayer\t" << std::setw(18)
440  << "mcWithMaxEnergyInCP\t" << std::setw(15) << "maxEnergyMCLinCP\t" << std::setw(20)
441  << "CPEnergyFractionInMCL"
442  << "\n";
443  LogDebug("MultiClusterAssociatorByEnergyScoreImpl")
444  << std::setw(8) << layerId << "\t" << std::setw(12) << cpId << "\t" << std::setw(15)
445  << caloParticles[cpId].energy() << "\t" << std::setw(15) << CPenergy << "\t" << std::setw(14)
446  << CPNumberOfHits << "\t" << std::setw(18) << mcWithMaxEnergyInCP << "\t" << std::setw(15)
447  << maxEnergyMCLperlayerinCP << "\t" << std::setw(20) << CPEnergyFractionInMCLperlayer << "\n";
448 #endif
449 
450  for (unsigned int i = 0; i < CPNumberOfHits; ++i) {
451  auto& cp_hitDetId = cPOnLayer[cpId][layerId].hits_and_fractions[i].first;
452  auto& cpFraction = cPOnLayer[cpId][layerId].hits_and_fractions[i].second;
453 
454  bool hitWithNoMCL = false;
455  if (cpFraction == 0.f)
456  continue; //hopefully this should never happen
457  auto hit_find_in_MCL = detIdToMultiClusterId_Map.find(cp_hitDetId);
458  if (hit_find_in_MCL == detIdToMultiClusterId_Map.end())
459  hitWithNoMCL = true;
460  auto itcheck = hitMap_->find(cp_hitDetId);
461  const HGCRecHit* hit = hits_[itcheck->second];
462  float hitEnergyWeight = hit->energy() * hit->energy();
463  for (auto& mcPair : cPOnLayer[cpId][layerId].multiClusterIdToEnergyAndScore) {
464  unsigned int multiClusterId = mcPair.first;
465  float mcFraction = 0.f;
466 
467  if (!hitWithNoMCL) {
468  auto findHitIt = std::find(detIdToMultiClusterId_Map[cp_hitDetId].begin(),
469  detIdToMultiClusterId_Map[cp_hitDetId].end(),
470  hgcal::detIdInfoInMultiCluster{multiClusterId, 0, 0.f});
471  if (findHitIt != detIdToMultiClusterId_Map[cp_hitDetId].end())
472  mcFraction = findHitIt->fraction;
473  }
474  //Observe here that we do not divide as before by the layer cluster energy weight. We should sum first
475  //over all layers and divide with the total CP energy over all layers.
476  if (mcPair.second.second == FLT_MAX) {
477  mcPair.second.second = 0.f;
478  }
479  mcPair.second.second += (mcFraction - cpFraction) * (mcFraction - cpFraction) * hitEnergyWeight;
480 #ifdef EDM_ML_DEBUG
481  LogDebug("HGCalValidator") << "multiClusterId:\t" << multiClusterId << "\tmcfraction,cpfraction:\t"
482  << mcFraction << ", " << cpFraction << "\thitEnergyWeight:\t" << hitEnergyWeight
483  << "\tcurrent score numerator:\t" << mcPair.second.second << "\n";
484 #endif
485  } // End of loop over MultiClusters linked to hits of this CaloParticle
486  } // End of loop over hits of CaloParticle on a Layer
487 #ifdef EDM_ML_DEBUG
488  if (cPOnLayer[cpId][layerId].multiClusterIdToEnergyAndScore.empty())
489  LogDebug("HGCalValidator") << "CP Id: \t" << cpId << "\t MCL id:\t-1 "
490  << "\t layer \t " << layerId << " Sub score in \t -1"
491  << "\n";
492 
493 #endif
494  }
495  }
496  return {cpsInMultiCluster, cPOnLayer};
497 }
for(int i=first, nt=offsets[nh];i< nt;i+=gridDim.x *blockDim.x)
T const * product() const
Definition: Handle.h:70
const std::unordered_map< DetId, const unsigned int > * hitMap_
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:19
std::vector< std::pair< uint32_t, float > > hits_and_fractions() const
Returns list of rechit IDs and fractions for this SimCluster.
Definition: SimCluster.h:188
std::vector< std::vector< hgcal::caloParticleOnALayer > > caloParticleToMultiCluster
Monte Carlo truth information used for tracking validation.
Definition: SimCluster.h:33
def unique(seq, keepstr=True)
Definition: tier0.py:24
double f[11][100]
Definition: DetId.h:17
static void removeCPFromPU(const std::vector< CaloParticle > &caloParticles, std::vector< size_t > &cPIndices, bool hardScatterOnly=true)
std::vector< std::vector< std::pair< unsigned int, float > > > multiClusterToCaloParticle
The Signals That Services Can Subscribe To This is based on ActivityRegistry h
Helper function to determine trigger accepts.
Definition: Activities.doc:4
def cp(fromDir, toDir, listOfFiles, overwrite=False, smallList=False)
#define LogDebug(id)

Member Data Documentation

◆ hardScatterOnly_

const bool MultiClusterAssociatorByEnergyScoreImpl::hardScatterOnly_
private

Definition at line 64 of file MultiClusterAssociatorByEnergyScoreImpl.h.

◆ hitMap_

const std::unordered_map<DetId, const unsigned int>* MultiClusterAssociatorByEnergyScoreImpl::hitMap_
private

Definition at line 66 of file MultiClusterAssociatorByEnergyScoreImpl.h.

Referenced by makeConnections().

◆ hits_

std::vector<const HGCRecHit *> MultiClusterAssociatorByEnergyScoreImpl::hits_
private

Definition at line 67 of file MultiClusterAssociatorByEnergyScoreImpl.h.

Referenced by makeConnections().

◆ layers_

unsigned MultiClusterAssociatorByEnergyScoreImpl::layers_
private

◆ productGetter_

edm::EDProductGetter const* MultiClusterAssociatorByEnergyScoreImpl::productGetter_
private

◆ recHitTools_

std::shared_ptr<hgcal::RecHitTools> MultiClusterAssociatorByEnergyScoreImpl::recHitTools_
private