CMS 3D CMS Logo

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