File indexing completed on 2023-03-17 11:21:02
0001 #include "DataFormats/Math/interface/deltaR.h"
0002 #include "DataFormats/ParticleFlowReco/interface/PFRecHit.h"
0003 #include "DataFormats/ParticleFlowReco/interface/PFRecHitFraction.h"
0004 #include "FWCore/Framework/interface/ConsumesCollector.h"
0005 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0006 #include "RecoParticleFlow/PFClusterProducer/interface/PFClusterBuilderBase.h"
0007
0008 #include "Math/GenVector/VectorUtil.h"
0009 #include "vdt/vdtMath.h"
0010
0011 #include <iterator>
0012 #include <unordered_map>
0013
0014 class Basic2DGenericPFlowClusterizer : public PFClusterBuilderBase {
0015 typedef Basic2DGenericPFlowClusterizer B2DGPF;
0016
0017 public:
0018 Basic2DGenericPFlowClusterizer(const edm::ParameterSet& conf, edm::ConsumesCollector& cc);
0019
0020 ~Basic2DGenericPFlowClusterizer() override = default;
0021 Basic2DGenericPFlowClusterizer(const B2DGPF&) = delete;
0022 B2DGPF& operator=(const B2DGPF&) = delete;
0023
0024 void update(const edm::EventSetup& es) override {
0025 _positionCalc->update(es);
0026 if (_allCellsPosCalc)
0027 _allCellsPosCalc->update(es);
0028 if (_convergencePosCalc)
0029 _convergencePosCalc->update(es);
0030 }
0031
0032 void buildClusters(const reco::PFClusterCollection&,
0033 const std::vector<bool>&,
0034 reco::PFClusterCollection& outclus) override;
0035
0036 private:
0037 const unsigned _maxIterations;
0038 const double _stoppingTolerance;
0039 const double _showerSigma2;
0040 const bool _excludeOtherSeeds;
0041 const double _minFracTot;
0042 const std::unordered_map<std::string, int> _layerMap;
0043
0044 std::unordered_map<int, std::pair<std::vector<int>, std::vector<double> > > _recHitEnergyNorms;
0045 std::unique_ptr<PFCPositionCalculatorBase> _allCellsPosCalc;
0046 std::unique_ptr<PFCPositionCalculatorBase> _convergencePosCalc;
0047
0048 void seedPFClustersFromTopo(const reco::PFCluster&, const std::vector<bool>&, reco::PFClusterCollection&) const;
0049
0050 void growPFClusters(const reco::PFCluster&,
0051 const std::vector<bool>&,
0052 const unsigned toleranceScaling,
0053 const unsigned iter,
0054 double dist,
0055 reco::PFClusterCollection&) const;
0056
0057 void prunePFClusters(reco::PFClusterCollection&) const;
0058 };
0059
0060 DEFINE_EDM_PLUGIN(PFClusterBuilderFactory, Basic2DGenericPFlowClusterizer, "Basic2DGenericPFlowClusterizer");
0061
0062 #ifdef PFLOW_DEBUG
0063 #define LOGVERB(x) edm::LogVerbatim(x)
0064 #define LOGWARN(x) edm::LogWarning(x)
0065 #define LOGERR(x) edm::LogError(x)
0066 #define LOGDRESSED(x) edm::LogInfo(x)
0067 #else
0068 #define LOGVERB(x) LogTrace(x)
0069 #define LOGWARN(x) edm::LogWarning(x)
0070 #define LOGERR(x) edm::LogError(x)
0071 #define LOGDRESSED(x) LogDebug(x)
0072 #endif
0073
0074 Basic2DGenericPFlowClusterizer::Basic2DGenericPFlowClusterizer(const edm::ParameterSet& conf,
0075 edm::ConsumesCollector& cc)
0076 : PFClusterBuilderBase(conf, cc),
0077 _maxIterations(conf.getParameter<unsigned>("maxIterations")),
0078 _stoppingTolerance(conf.getParameter<double>("stoppingTolerance")),
0079 _showerSigma2(std::pow(conf.getParameter<double>("showerSigma"), 2.0)),
0080 _excludeOtherSeeds(conf.getParameter<bool>("excludeOtherSeeds")),
0081 _minFracTot(conf.getParameter<double>("minFracTot")),
0082 _layerMap({{"PS2", (int)PFLayer::PS2},
0083 {"PS1", (int)PFLayer::PS1},
0084 {"ECAL_ENDCAP", (int)PFLayer::ECAL_ENDCAP},
0085 {"ECAL_BARREL", (int)PFLayer::ECAL_BARREL},
0086 {"NONE", (int)PFLayer::NONE},
0087 {"HCAL_BARREL1", (int)PFLayer::HCAL_BARREL1},
0088 {"HCAL_BARREL2_RING0", (int)PFLayer::HCAL_BARREL2},
0089 {"HCAL_BARREL2_RING1", 100 * (int)PFLayer::HCAL_BARREL2},
0090 {"HCAL_ENDCAP", (int)PFLayer::HCAL_ENDCAP},
0091 {"HF_EM", (int)PFLayer::HF_EM},
0092 {"HF_HAD", (int)PFLayer::HF_HAD}}) {
0093 const std::vector<edm::ParameterSet>& thresholds = conf.getParameterSetVector("recHitEnergyNorms");
0094 for (const auto& pset : thresholds) {
0095 const std::string& det = pset.getParameter<std::string>("detector");
0096
0097 std::vector<int> depths;
0098 std::vector<double> rhE_norm;
0099
0100 if (det == std::string("HCAL_BARREL1") || det == std::string("HCAL_ENDCAP")) {
0101 depths = pset.getParameter<std::vector<int> >("depths");
0102 rhE_norm = pset.getParameter<std::vector<double> >("recHitEnergyNorm");
0103 } else {
0104 depths.push_back(0);
0105 rhE_norm.push_back(pset.getParameter<double>("recHitEnergyNorm"));
0106 }
0107
0108 if (rhE_norm.size() != depths.size()) {
0109 throw cms::Exception("InvalidPFRecHitThreshold")
0110 << "PFlowClusterizerThreshold mismatch with the numbers of depths";
0111 }
0112
0113 auto entry = _layerMap.find(det);
0114 if (entry == _layerMap.end()) {
0115 throw cms::Exception("InvalidDetectorLayer") << "Detector layer : " << det << " is not in the list of recognized"
0116 << " detector layers!";
0117 }
0118 _recHitEnergyNorms.emplace(_layerMap.find(det)->second, std::make_pair(depths, rhE_norm));
0119 }
0120
0121 if (conf.exists("allCellsPositionCalc")) {
0122 const edm::ParameterSet& acConf = conf.getParameterSet("allCellsPositionCalc");
0123 const std::string& algoac = acConf.getParameter<std::string>("algoName");
0124 _allCellsPosCalc = PFCPositionCalculatorFactory::get()->create(algoac, acConf, cc);
0125 }
0126
0127 if (conf.exists("positionCalcForConvergence")) {
0128 const edm::ParameterSet& convConf = conf.getParameterSet("positionCalcForConvergence");
0129 const std::string& algoconv = convConf.getParameter<std::string>("algoName");
0130 _convergencePosCalc = PFCPositionCalculatorFactory::get()->create(algoconv, convConf, cc);
0131 }
0132 }
0133
0134 void Basic2DGenericPFlowClusterizer::buildClusters(const reco::PFClusterCollection& input,
0135 const std::vector<bool>& seedable,
0136 reco::PFClusterCollection& output) {
0137 reco::PFClusterCollection clustersInTopo;
0138 for (const auto& topocluster : input) {
0139 clustersInTopo.clear();
0140 seedPFClustersFromTopo(topocluster, seedable, clustersInTopo);
0141 const unsigned tolScal = std::pow(std::max(1.0, clustersInTopo.size() - 1.0), 2.0);
0142 growPFClusters(topocluster, seedable, tolScal, 0, tolScal, clustersInTopo);
0143
0144
0145
0146 prunePFClusters(clustersInTopo);
0147
0148 if (_convergencePosCalc) {
0149
0150 _convergencePosCalc->calculateAndSetPositions(clustersInTopo);
0151 } else {
0152 if (clustersInTopo.size() == 1 && _allCellsPosCalc) {
0153 _allCellsPosCalc->calculateAndSetPosition(clustersInTopo.back());
0154 } else {
0155 _positionCalc->calculateAndSetPositions(clustersInTopo);
0156 }
0157 }
0158 for (auto& clusterout : clustersInTopo) {
0159 output.insert(output.end(), std::move(clusterout));
0160 }
0161 }
0162 }
0163
0164 void Basic2DGenericPFlowClusterizer::seedPFClustersFromTopo(const reco::PFCluster& topo,
0165 const std::vector<bool>& seedable,
0166 reco::PFClusterCollection& initialPFClusters) const {
0167 const auto& recHitFractions = topo.recHitFractions();
0168 for (const auto& rhf : recHitFractions) {
0169 if (!seedable[rhf.recHitRef().key()])
0170 continue;
0171 initialPFClusters.push_back(reco::PFCluster());
0172 reco::PFCluster& current = initialPFClusters.back();
0173 current.addRecHitFraction(rhf);
0174 current.setSeed(rhf.recHitRef()->detId());
0175 if (_convergencePosCalc) {
0176 _convergencePosCalc->calculateAndSetPosition(current);
0177 } else {
0178 _positionCalc->calculateAndSetPosition(current);
0179 }
0180 }
0181 }
0182
0183 void Basic2DGenericPFlowClusterizer::growPFClusters(const reco::PFCluster& topo,
0184 const std::vector<bool>& seedable,
0185 const unsigned toleranceScaling,
0186 const unsigned iter,
0187 double diff,
0188 reco::PFClusterCollection& clusters) const {
0189 if (iter >= _maxIterations) {
0190 LOGDRESSED("Basic2DGenericPFlowClusterizer:growAndStabilizePFClusters")
0191 << "reached " << _maxIterations << " iterations, terminated position "
0192 << "fit with diff = " << diff;
0193 }
0194 if (iter >= _maxIterations || diff <= _stoppingTolerance * toleranceScaling)
0195 return;
0196
0197 std::vector<reco::PFCluster::REPPoint> clus_prev_pos;
0198 for (auto& cluster : clusters) {
0199 const reco::PFCluster::REPPoint& repp = cluster.positionREP();
0200 clus_prev_pos.emplace_back(repp.rho(), repp.eta(), repp.phi());
0201 if (_convergencePosCalc) {
0202 if (clusters.size() == 1 && _allCellsPosCalc) {
0203 _allCellsPosCalc->calculateAndSetPosition(cluster);
0204 } else {
0205 _positionCalc->calculateAndSetPosition(cluster);
0206 }
0207 }
0208 cluster.resetHitsAndFractions();
0209 }
0210
0211 std::vector<double> dist2, frac;
0212 double fractot = 0;
0213 for (const reco::PFRecHitFraction& rhf : topo.recHitFractions()) {
0214 const reco::PFRecHitRef& refhit = rhf.recHitRef();
0215 int cell_layer = (int)refhit->layer();
0216 if (cell_layer == PFLayer::HCAL_BARREL2 && std::abs(refhit->positionREP().eta()) > 0.34) {
0217 cell_layer *= 100;
0218 }
0219
0220 math::XYZPoint topocellpos_xyz(refhit->position());
0221 dist2.clear();
0222 frac.clear();
0223 fractot = 0;
0224
0225 double recHitEnergyNorm = 0.;
0226 auto const& recHitEnergyNormDepthPair = _recHitEnergyNorms.find(cell_layer)->second;
0227
0228 for (unsigned int j = 0; j < recHitEnergyNormDepthPair.second.size(); ++j) {
0229 int depth = recHitEnergyNormDepthPair.first[j];
0230
0231 if ((cell_layer == PFLayer::HCAL_BARREL1 && refhit->depth() == depth) ||
0232 (cell_layer == PFLayer::HCAL_ENDCAP && refhit->depth() == depth) ||
0233 (cell_layer != PFLayer::HCAL_ENDCAP && cell_layer != PFLayer::HCAL_BARREL1))
0234 recHitEnergyNorm = recHitEnergyNormDepthPair.second[j];
0235 }
0236
0237
0238 for (auto& cluster : clusters) {
0239 const math::XYZPoint& clusterpos_xyz = cluster.position();
0240 const math::XYZVector deltav = clusterpos_xyz - topocellpos_xyz;
0241 const double d2 = deltav.Mag2() / _showerSigma2;
0242 dist2.emplace_back(d2);
0243 if (d2 > 100) {
0244 LOGDRESSED("Basic2DGenericPFlowClusterizer:growAndStabilizePFClusters")
0245 << "Warning! :: pfcluster-topocell distance is too large! d= " << d2;
0246 }
0247
0248
0249 double fraction;
0250 if (refhit->detId() == cluster.seed() && _excludeOtherSeeds) {
0251 fraction = 1.0;
0252 } else if (seedable[refhit.key()] && _excludeOtherSeeds) {
0253 fraction = 0.0;
0254 } else {
0255 fraction = cluster.energy() / recHitEnergyNorm * vdt::fast_expf(-0.5 * d2);
0256 }
0257 fractot += fraction;
0258 frac.emplace_back(fraction);
0259 }
0260 for (unsigned i = 0; i < clusters.size(); ++i) {
0261 if (fractot > _minFracTot || (refhit->detId() == clusters[i].seed() && fractot > 0.0)) {
0262 frac[i] /= fractot;
0263 } else {
0264 continue;
0265 }
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277 if (dist2[i] < 100.0 || frac[i] > 0.9999) {
0278 clusters[i].addRecHitFraction(reco::PFRecHitFraction(refhit, frac[i]));
0279 }
0280 }
0281 }
0282
0283 double diff2 = 0.0;
0284 for (unsigned i = 0; i < clusters.size(); ++i) {
0285 if (_convergencePosCalc) {
0286 _convergencePosCalc->calculateAndSetPosition(clusters[i]);
0287 } else {
0288 if (clusters.size() == 1 && _allCellsPosCalc) {
0289 _allCellsPosCalc->calculateAndSetPosition(clusters[i]);
0290 } else {
0291 _positionCalc->calculateAndSetPosition(clusters[i]);
0292 }
0293 }
0294 const double delta2 = reco::deltaR2(clusters[i].positionREP(), clus_prev_pos[i]);
0295 if (delta2 > diff2)
0296 diff2 = delta2;
0297 }
0298 diff = std::sqrt(diff2);
0299 dist2.clear();
0300 frac.clear();
0301 clus_prev_pos.clear();
0302 growPFClusters(topo, seedable, toleranceScaling, iter + 1, diff, clusters);
0303 }
0304
0305 void Basic2DGenericPFlowClusterizer::prunePFClusters(reco::PFClusterCollection& clusters) const {
0306 for (auto& cluster : clusters) {
0307 cluster.pruneUsing([&](const reco::PFRecHitFraction& rhf) { return rhf.fraction() > _minFractionToKeep; });
0308 }
0309 }