CMS 3D CMS Logo

Basic2DGenericPFlowClusterizer.cc
Go to the documentation of this file.
9 
10 #include "Math/GenVector/VectorUtil.h"
11 #include "vdt/vdtMath.h"
12 
13 #include <iterator>
14 #include <unordered_map>
15 
18 
19 public:
21 
22  ~Basic2DGenericPFlowClusterizer() override = default;
23  Basic2DGenericPFlowClusterizer(const B2DGPF&) = delete;
24  B2DGPF& operator=(const B2DGPF&) = delete;
25 
26  void update(const edm::EventSetup& es) override {
27  _positionCalc->update(es);
28  if (_allCellsPosCalc)
29  _allCellsPosCalc->update(es);
31  _convergencePosCalc->update(es);
32  }
33 
35  const std::vector<bool>&,
37  const HcalPFCuts*) override;
38 
39 private:
40  const unsigned _maxIterations;
41  const double _stoppingTolerance;
42  const double _showerSigma2;
43  const bool _excludeOtherSeeds;
44  const double _minFracTot;
45  const std::unordered_map<std::string, int> _layerMap;
46 
47  std::unordered_map<int, std::pair<std::vector<int>, std::vector<double> > > _recHitEnergyNorms;
48  std::unique_ptr<PFCPositionCalculatorBase> _allCellsPosCalc;
49  std::unique_ptr<PFCPositionCalculatorBase> _convergencePosCalc;
50 
52  const std::vector<bool>&,
54  const HcalPFCuts*) const;
55 
56  void growPFClusters(const reco::PFCluster&,
57  const std::vector<bool>&,
58  const unsigned toleranceScaling,
59  const unsigned iter,
60  double dist,
62  const HcalPFCuts*) const;
63 
65 };
66 
68 
69 #ifdef PFLOW_DEBUG
70 #define LOGVERB(x) edm::LogVerbatim(x)
71 #define LOGWARN(x) edm::LogWarning(x)
72 #define LOGERR(x) edm::LogError(x)
73 #define LOGDRESSED(x) edm::LogInfo(x)
74 #else
75 #define LOGVERB(x) LogTrace(x)
76 #define LOGWARN(x) edm::LogWarning(x)
77 #define LOGERR(x) edm::LogError(x)
78 #define LOGDRESSED(x) LogDebug(x)
79 #endif
80 
83  : PFClusterBuilderBase(conf, cc),
84  _maxIterations(conf.getParameter<unsigned>("maxIterations")),
85  _stoppingTolerance(conf.getParameter<double>("stoppingTolerance")),
86  _showerSigma2(std::pow(conf.getParameter<double>("showerSigma"), 2.0)),
87  _excludeOtherSeeds(conf.getParameter<bool>("excludeOtherSeeds")),
88  _minFracTot(conf.getParameter<double>("minFracTot")),
89  _layerMap({{"PS2", (int)PFLayer::PS2},
90  {"PS1", (int)PFLayer::PS1},
91  {"ECAL_ENDCAP", (int)PFLayer::ECAL_ENDCAP},
92  {"ECAL_BARREL", (int)PFLayer::ECAL_BARREL},
93  {"NONE", (int)PFLayer::NONE},
94  {"HCAL_BARREL1", (int)PFLayer::HCAL_BARREL1},
95  {"HCAL_BARREL2_RING0", (int)PFLayer::HCAL_BARREL2},
96  {"HCAL_BARREL2_RING1", 100 * (int)PFLayer::HCAL_BARREL2},
97  {"HCAL_ENDCAP", (int)PFLayer::HCAL_ENDCAP},
98  {"HF_EM", (int)PFLayer::HF_EM},
99  {"HF_HAD", (int)PFLayer::HF_HAD}}) {
100  const std::vector<edm::ParameterSet>& thresholds = conf.getParameterSetVector("recHitEnergyNorms");
101  for (const auto& pset : thresholds) {
102  const std::string& det = pset.getParameter<std::string>("detector");
103 
104  std::vector<int> depths;
105  std::vector<double> rhE_norm;
106 
107  if (det == std::string("HCAL_BARREL1") || det == std::string("HCAL_ENDCAP")) {
108  depths = pset.getParameter<std::vector<int> >("depths");
109  rhE_norm = pset.getParameter<std::vector<double> >("recHitEnergyNorm");
110  } else {
111  depths.push_back(0);
112  rhE_norm.push_back(pset.getParameter<double>("recHitEnergyNorm"));
113  }
114 
115  if (rhE_norm.size() != depths.size()) {
116  throw cms::Exception("InvalidPFRecHitThreshold")
117  << "PFlowClusterizerThreshold mismatch with the numbers of depths";
118  }
119 
120  auto entry = _layerMap.find(det);
121  if (entry == _layerMap.end()) {
122  throw cms::Exception("InvalidDetectorLayer") << "Detector layer : " << det << " is not in the list of recognized"
123  << " detector layers!";
124  }
125  _recHitEnergyNorms.emplace(_layerMap.find(det)->second, std::make_pair(depths, rhE_norm));
126  }
127 
128  if (conf.exists("allCellsPositionCalc")) {
129  const edm::ParameterSet& acConf = conf.getParameterSet("allCellsPositionCalc");
130  const std::string& algoac = acConf.getParameter<std::string>("algoName");
131  _allCellsPosCalc = PFCPositionCalculatorFactory::get()->create(algoac, acConf, cc);
132  }
133  // if necessary a third pos calc for convergence testing
134  if (conf.exists("positionCalcForConvergence")) {
135  const edm::ParameterSet& convConf = conf.getParameterSet("positionCalcForConvergence");
136  const std::string& algoconv = convConf.getParameter<std::string>("algoName");
137  _convergencePosCalc = PFCPositionCalculatorFactory::get()->create(algoconv, convConf, cc);
138  }
139 }
140 
142  const std::vector<bool>& seedable,
144  const HcalPFCuts* hcalCuts) {
145  reco::PFClusterCollection clustersInTopo;
146  for (const auto& topocluster : input) {
147  clustersInTopo.clear();
148  seedPFClustersFromTopo(topocluster, seedable, clustersInTopo, hcalCuts);
149  const unsigned tolScal = std::pow(std::max(1.0, clustersInTopo.size() - 1.0), 2.0);
150  growPFClusters(topocluster, seedable, tolScal, 0, tolScal, clustersInTopo, hcalCuts);
151  // step added by Josh Bendavid, removes low-fraction clusters
152  // did not impact position resolution with fraction cut of 1e-7
153  // decreases the size of each pf cluster considerably
154  prunePFClusters(clustersInTopo);
155  // recalculate the positions of the pruned clusters
156  if (_convergencePosCalc) {
157  // if defined, use the special position calculation for convergence tests
158  _convergencePosCalc->calculateAndSetPositions(clustersInTopo, hcalCuts);
159  } else {
160  if (clustersInTopo.size() == 1 && _allCellsPosCalc) {
161  _allCellsPosCalc->calculateAndSetPosition(clustersInTopo.back(), hcalCuts);
162  } else {
163  _positionCalc->calculateAndSetPositions(clustersInTopo, hcalCuts);
164  }
165  }
166  for (auto& clusterout : clustersInTopo) {
167  output.insert(output.end(), std::move(clusterout));
168  }
169  }
170 }
171 
173  const std::vector<bool>& seedable,
174  reco::PFClusterCollection& initialPFClusters,
175  const HcalPFCuts* hcalCuts) const {
176  const auto& recHitFractions = topo.recHitFractions();
177  for (const auto& rhf : recHitFractions) {
178  if (!seedable[rhf.recHitRef().key()])
179  continue;
180  initialPFClusters.push_back(reco::PFCluster());
181  reco::PFCluster& current = initialPFClusters.back();
182  current.addRecHitFraction(rhf);
183  current.setSeed(rhf.recHitRef()->detId());
184  if (_convergencePosCalc) {
185  _convergencePosCalc->calculateAndSetPosition(current, hcalCuts);
186  } else {
187  _positionCalc->calculateAndSetPosition(current, hcalCuts);
188  }
189  }
190 }
191 
193  const std::vector<bool>& seedable,
194  const unsigned toleranceScaling,
195  const unsigned iter,
196  double diff,
198  const HcalPFCuts* hcalCuts) const {
199  if (iter >= _maxIterations) {
200  LOGDRESSED("Basic2DGenericPFlowClusterizer:growAndStabilizePFClusters")
201  << "reached " << _maxIterations << " iterations, terminated position "
202  << "fit with diff = " << diff;
203  }
204  if (iter >= _maxIterations || diff <= _stoppingTolerance * toleranceScaling)
205  return;
206  // reset the rechits in this cluster, keeping the previous position
207  std::vector<reco::PFCluster::REPPoint> clus_prev_pos;
208  for (auto& cluster : clusters) {
209  const reco::PFCluster::REPPoint& repp = cluster.positionREP();
210  clus_prev_pos.emplace_back(repp.rho(), repp.eta(), repp.phi());
211  if (_convergencePosCalc) {
212  if (clusters.size() == 1 && _allCellsPosCalc) {
213  _allCellsPosCalc->calculateAndSetPosition(cluster, hcalCuts);
214  } else {
215  _positionCalc->calculateAndSetPosition(cluster, hcalCuts);
216  }
217  }
218  cluster.resetHitsAndFractions();
219  }
220  // loop over topo cluster and grow current PFCluster hypothesis
221  std::vector<double> dist2, frac;
222  double fractot = 0;
223  for (const reco::PFRecHitFraction& rhf : topo.recHitFractions()) {
224  const reco::PFRecHitRef& refhit = rhf.recHitRef();
225  int cell_layer = (int)refhit->layer();
226  if (cell_layer == PFLayer::HCAL_BARREL2 && std::abs(refhit->positionREP().eta()) > 0.34) {
227  cell_layer *= 100;
228  }
229 
230  math::XYZPoint topocellpos_xyz(refhit->position());
231  dist2.clear();
232  frac.clear();
233  fractot = 0;
234 
235  double recHitEnergyNorm = 0.;
236  auto const& recHitEnergyNormDepthPair = _recHitEnergyNorms.find(cell_layer)->second;
237 
238  if (hcalCuts != nullptr && // this means, cutsFromDB is set to True in PFClusterProducer.cc
239  (cell_layer == PFLayer::HCAL_BARREL1 || cell_layer == PFLayer::HCAL_ENDCAP)) {
240  HcalDetId thisId = refhit->detId();
241  const HcalPFCut* item = hcalCuts->getValues(thisId.rawId());
242  recHitEnergyNorm = item->noiseThreshold();
243  } else {
244  for (unsigned int j = 0; j < recHitEnergyNormDepthPair.second.size(); ++j) {
245  int depth = recHitEnergyNormDepthPair.first[j];
246  if ((cell_layer == PFLayer::HCAL_BARREL1 && refhit->depth() == depth) ||
247  (cell_layer == PFLayer::HCAL_ENDCAP && refhit->depth() == depth) ||
248  (cell_layer != PFLayer::HCAL_ENDCAP && cell_layer != PFLayer::HCAL_BARREL1))
249  recHitEnergyNorm = recHitEnergyNormDepthPair.second[j];
250  }
251  }
252 
253  // add rechits to clusters, calculating fraction based on distance
254  for (auto& cluster : clusters) {
255  const math::XYZPoint& clusterpos_xyz = cluster.position();
256  const math::XYZVector deltav = clusterpos_xyz - topocellpos_xyz;
257  const double d2 = deltav.Mag2() / _showerSigma2;
258  dist2.emplace_back(d2);
259  if (d2 > 100) {
260  LOGDRESSED("Basic2DGenericPFlowClusterizer:growAndStabilizePFClusters")
261  << "Warning! :: pfcluster-topocell distance is too large! d= " << d2;
262  }
263 
264  // fraction assignment logic
265  double fraction;
266  if (refhit->detId() == cluster.seed() && _excludeOtherSeeds) {
267  fraction = 1.0;
268  } else if (seedable[refhit.key()] && _excludeOtherSeeds) {
269  fraction = 0.0;
270  } else {
271  fraction = cluster.energy() / recHitEnergyNorm * vdt::fast_expf(-0.5 * d2);
272  }
273  fractot += fraction;
274  frac.emplace_back(fraction);
275  }
276  for (unsigned i = 0; i < clusters.size(); ++i) {
277  if (fractot > _minFracTot || (refhit->detId() == clusters[i].seed() && fractot > 0.0)) {
278  frac[i] /= fractot;
279  } else {
280  continue;
281  }
282  // if the fraction has been set to 0, the cell
283  // is now added to the cluster - careful ! (PJ, 19/07/08)
284  // BUT KEEP ONLY CLOSE CELLS OTHERWISE MEMORY JUST EXPLOSES
285  // (PJ, 15/09/08 <- similar to what existed before the
286  // previous bug fix, but keeps the close seeds inside,
287  // even if their fraction was set to zero.)
288  // Also add a protection to keep the seed in the cluster
289  // when the latter gets far from the former. These cases
290  // (about 1% of the clusters) need to be studied, as
291  // they create fake photons, in general.
292  // (PJ, 16/09/08)
293  if (dist2[i] < 100.0 || frac[i] > 0.9999) {
294  clusters[i].addRecHitFraction(reco::PFRecHitFraction(refhit, frac[i]));
295  }
296  }
297  }
298  // recalculate positions and calculate convergence parameter
299  double diff2 = 0.0;
300  for (unsigned i = 0; i < clusters.size(); ++i) {
301  if (_convergencePosCalc) {
302  _convergencePosCalc->calculateAndSetPosition(clusters[i], hcalCuts);
303  } else {
304  if (clusters.size() == 1 && _allCellsPosCalc) {
305  _allCellsPosCalc->calculateAndSetPosition(clusters[i], hcalCuts);
306  } else {
307  _positionCalc->calculateAndSetPosition(clusters[i], hcalCuts);
308  }
309  }
310  const double delta2 = reco::deltaR2(clusters[i].positionREP(), clus_prev_pos[i]);
311  if (delta2 > diff2)
312  diff2 = delta2;
313  }
314  diff = std::sqrt(diff2);
315  dist2.clear();
316  frac.clear();
317  clus_prev_pos.clear(); // avoid badness
318  growPFClusters(topo, seedable, toleranceScaling, iter + 1, diff, clusters, hcalCuts);
319 }
320 
322  for (auto& cluster : clusters) {
323  cluster.pruneUsing([&](const reco::PFRecHitFraction& rhf) { return rhf.fraction() > _minFractionToKeep; });
324  }
325 }
T getParameter(std::string const &) const
Definition: ParameterSet.h:307
Particle flow cluster, see clustering algorithm in PFClusterAlgo.
Definition: PFCluster.h:42
uint32_t cc[maxCellsPerHit]
Definition: gpuFishbone.h:49
std::unique_ptr< PosCalc > _positionCalc
ParameterSet const & getParameterSet(std::string const &) const
const std::unordered_map< std::string, int > _layerMap
Fraction of a PFRecHit (rechits can be shared between several PFCluster&#39;s)
const std::vector< reco::PFRecHitFraction > & recHitFractions() const
vector of rechit fractions
Definition: PFCluster.h:65
std::unique_ptr< PFCPositionCalculatorBase > _convergencePosCalc
#define LOGDRESSED(x)
key_type key() const
Accessor for product key.
Definition: Ref.h:250
void seedPFClustersFromTopo(const reco::PFCluster &, const std::vector< bool > &, reco::PFClusterCollection &, const HcalPFCuts *) const
const Item * getValues(DetId fId, bool throwOnFail=true) const
static std::string const input
Definition: EdmProvDump.cc:50
void setSeed(const DetId &id)
Definition: CaloCluster.h:145
Basic2DGenericPFlowClusterizer(const edm::ParameterSet &conf, edm::ConsumesCollector &cc)
std::unique_ptr< PFCPositionCalculatorBase > _allCellsPosCalc
void prunePFClusters(reco::PFClusterCollection &) const
T sqrt(T t)
Definition: SSEVec.h:19
~Basic2DGenericPFlowClusterizer() override=default
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
B2DGPF & operator=(const B2DGPF &)=delete
constexpr auto deltaR2(const T1 &t1, const T2 &t2) -> decltype(t1.eta())
Definition: deltaR.h:16
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
std::unordered_map< int, std::pair< std::vector< int >, std::vector< double > > > _recHitEnergyNorms
void addRecHitFraction(const reco::PFRecHitFraction &frac)
add a given fraction of the rechit
Definition: PFCluster.cc:33
float fast_expf(float x)
ROOT::Math::PositionVector3D< ROOT::Math::CylindricalEta3D< double > > REPPoint
Definition: PFCluster.h:48
std::vector< PFCluster > PFClusterCollection
collection of PFCluster objects
Definition: PFClusterFwd.h:9
#define DEFINE_EDM_PLUGIN(factory, type, name)
Definition: output.py:1
#define get
void growPFClusters(const reco::PFCluster &, const std::vector< bool > &, const unsigned toleranceScaling, const unsigned iter, double dist, reco::PFClusterCollection &, const HcalPFCuts *) const
void update(const edm::EventSetup &es) override
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:29
void buildClusters(const reco::PFClusterCollection &, const std::vector< bool > &, reco::PFClusterCollection &outclus, const HcalPFCuts *) override
def move(src, dest)
Definition: eostools.py:511