diff --git a/RecoParticleFlow/PFClusterProducer/BuildFile.xml b/RecoParticleFlow/PFClusterProducer/BuildFile.xml
index fcee687e8e160..30ca19dee8af4 100644
--- a/RecoParticleFlow/PFClusterProducer/BuildFile.xml
+++ b/RecoParticleFlow/PFClusterProducer/BuildFile.xml
@@ -12,6 +12,7 @@
+
diff --git a/RecoParticleFlow/PFClusterProducer/plugins/SimMappers/RealisticCluster.h b/RecoParticleFlow/PFClusterProducer/plugins/SimMappers/RealisticCluster.h
new file mode 100644
index 0000000000000..d0e2a78c86cf9
--- /dev/null
+++ b/RecoParticleFlow/PFClusterProducer/plugins/SimMappers/RealisticCluster.h
@@ -0,0 +1,140 @@
+#ifndef __RecoParticleFlow_PFClusterProducer_RealisticCluster_H__
+#define __RecoParticleFlow_PFClusterProducer_RealisticCluster_H__
+
+#include
+#include
+#include
+
+class RealisticCluster
+{
+ using Hit3DPosition = std::array;
+
+ public:
+
+ // for each SimCluster and for each layer, we store the position of the most energetic hit of the simcluster in the layer
+
+ struct LayerInfo
+ {
+ Hit3DPosition centerOfGravityAtLayer_;
+ Hit3DPosition maxHitPosAtLayer_;
+ float maxEnergyHitAtLayer_;
+ };
+
+ RealisticCluster():
+ totalEnergy(0.f),
+ exclusiveEnergy(0.f),
+ visible(true)
+ {
+
+ }
+
+ void increaseEnergy(float value)
+ {
+ totalEnergy+=value;
+ }
+ void increaseExclusiveEnergy(float value)
+ {
+ exclusiveEnergy+=value;
+ }
+
+ float getExclusiveEnergyFraction() const
+ {
+ float fraction = 0.f;
+ if(totalEnergy>0.f){
+ fraction = exclusiveEnergy/totalEnergy;
+ }
+ return fraction;
+ }
+
+ float getEnergy() const
+ {
+ return totalEnergy;
+ }
+
+ float getExclusiveEnergy() const
+ {
+ return exclusiveEnergy;
+ }
+
+ bool isVisible() const
+ {
+ return visible;
+ }
+
+ void setVisible(bool vis)
+ {
+ visible = vis;
+ }
+
+ void setCenterOfGravity(unsigned int layerId, const Hit3DPosition& position)
+ {
+ layerInfo_[layerId].centerOfGravityAtLayer_ = position;
+ }
+
+ Hit3DPosition getCenterOfGravity(unsigned int layerId) const
+ {
+ return layerInfo_[layerId].centerOfGravityAtLayer_ ;
+ }
+
+ bool setMaxEnergyHit(unsigned int layerId, float newEnergy, const Hit3DPosition position)
+ {
+ if (newEnergy > layerInfo_[layerId].maxEnergyHitAtLayer_)
+ {
+ layerInfo_[layerId].maxEnergyHitAtLayer_ = newEnergy;
+ layerInfo_[layerId].maxHitPosAtLayer_ = position;
+ return true;
+ }
+ else
+ return false;
+ }
+
+ Hit3DPosition getMaxEnergyPosition (unsigned int layerId) const
+ {
+ return layerInfo_[layerId].maxHitPosAtLayer_;
+ }
+
+ float getMaxEnergy(unsigned int layerId) const
+ {
+ return layerInfo_[layerId].maxEnergyHitAtLayer_;
+ }
+
+ void setLayersNum(unsigned int numberOfLayers)
+ {
+ layerInfo_.resize(numberOfLayers);
+ }
+
+ unsigned int getLayersNum() const
+ {
+ return layerInfo_.size();
+ }
+
+ void addHitAndFraction(unsigned int hit, float fraction)
+ {
+ hitIdsAndFractions_.emplace_back(hit,fraction);
+ }
+
+ void modifyFractionForHitId(float fraction, unsigned int hitId)
+ {
+ auto it = std::find_if( hitIdsAndFractions_.begin(), hitIdsAndFractions_.end(),
+ [&hitId](const std::pair& element){ return element.first == hitId;} );
+
+ it->second = fraction;
+ }
+
+ void modifyFractionByIndex(float fraction, unsigned int index)
+ {
+ hitIdsAndFractions_[index].second = fraction;
+ }
+
+ const std::vector< std::pair > & hitsIdsAndFractions() const { return hitIdsAndFractions_; }
+
+ private:
+ std::vector > hitIdsAndFractions_;
+ std::vector layerInfo_;
+
+ float totalEnergy;
+ float exclusiveEnergy;
+ bool visible;
+};
+
+#endif
diff --git a/RecoParticleFlow/PFClusterProducer/plugins/SimMappers/RealisticHitToClusterAssociator.h b/RecoParticleFlow/PFClusterProducer/plugins/SimMappers/RealisticHitToClusterAssociator.h
new file mode 100644
index 0000000000000..b6d9944ed76d1
--- /dev/null
+++ b/RecoParticleFlow/PFClusterProducer/plugins/SimMappers/RealisticHitToClusterAssociator.h
@@ -0,0 +1,337 @@
+#ifndef __RecoParticleFlow_PFClusterProducer_RealisticHitToClusterAssociator_H__
+#define __RecoParticleFlow_PFClusterProducer_RealisticHitToClusterAssociator_H__
+/////////////////////////
+// Author: Felice Pantaleo
+// Date: 30/06/2017
+// Email: felice@cern.ch
+/////////////////////////
+#include
+#include
+#include "RealisticCluster.h"
+
+namespace
+{
+
+float getDecayLength(unsigned int layer, unsigned int fhOffset, unsigned int bhOffset)
+{
+ constexpr float eeDecayLengthInLayer = 2.f;
+ constexpr float fhDecayLengthInLayer = 1.5f;
+ constexpr float bhDecayLengthInLayer = 1.f;
+
+ if (layer <= fhOffset)
+ return eeDecayLengthInLayer;
+ else if (layer > fhOffset && layer <= bhOffset)
+ return fhDecayLengthInLayer;
+ else
+ return bhDecayLengthInLayer;
+}
+}
+
+
+class RealisticHitToClusterAssociator
+{
+ using Hit3DPosition = std::array;
+
+ public:
+
+ struct RealisticHit
+ {
+ struct HitToCluster
+ {
+ unsigned int simClusterId_;
+ float mcEnergyFraction_;
+ float distanceFromMaxHit_;
+ float realisticEnergyFraction_;
+ };
+
+ Hit3DPosition hitPosition_;
+ float totalEnergy_;
+ unsigned int layerId_;
+ std::vector hitToCluster_;
+ };
+
+ void init(std::size_t numberOfHits, std::size_t numberOfSimClusters,
+ std::size_t numberOfLayers)
+ {
+ realisticHits_.resize(numberOfHits);
+ realisticSimClusters_.resize(numberOfSimClusters);
+ for(auto& sc: realisticSimClusters_)
+ sc.setLayersNum(numberOfLayers);
+ }
+
+ void insertHitPosition(float x, float y, float z, unsigned int hitIndex)
+ {
+ realisticHits_[hitIndex].hitPosition_ = {{x,y,z}};
+ }
+
+ void insertLayerId(unsigned int layerId, unsigned int hitIndex)
+ {
+ realisticHits_[hitIndex].layerId_ = layerId;
+ }
+
+ void insertHitEnergy(float energy, unsigned int hitIndex)
+ {
+ realisticHits_[hitIndex].totalEnergy_ = energy;
+ }
+
+ void insertSimClusterIdAndFraction(unsigned int scIdx, float fraction,
+ unsigned int hitIndex, float associatedEnergy)
+ {
+ realisticHits_[hitIndex].hitToCluster_.emplace_back(RealisticHit::HitToCluster{scIdx, fraction, 0.f, 0.f});
+ realisticSimClusters_[scIdx].setMaxEnergyHit(realisticHits_[hitIndex].layerId_, associatedEnergy, realisticHits_[hitIndex].hitPosition_);
+ }
+
+ float XYdistanceFromMaxHit(unsigned int hitId, unsigned int clusterId)
+ {
+ auto l = realisticHits_[hitId].layerId_;
+ const auto& maxHitPosition = realisticSimClusters_[clusterId].getMaxEnergyPosition(l);
+ float distanceSquared = std::pow((realisticHits_[hitId].hitPosition_[0] - maxHitPosition[0]),2) + std::pow((realisticHits_[hitId].hitPosition_[1] - maxHitPosition[1]),2);
+ return std::sqrt(distanceSquared);
+ }
+
+ float XYdistanceFromPointOnSameLayer(unsigned int hitId, const Hit3DPosition& point)
+ {
+ float distanceSquared = std::pow((realisticHits_[hitId].hitPosition_[0] - point[0]),2) + std::pow((realisticHits_[hitId].hitPosition_[1] - point[1]),2);
+ return std::sqrt(distanceSquared);
+ }
+
+ void computeAssociation( float exclusiveFraction, bool useMCFractionsForExclEnergy, unsigned int fhOffset, unsigned int bhOffset)
+ {
+ //if more than exclusiveFraction of a hit's energy belongs to a cluster, that rechit is not counted as shared
+ unsigned int numberOfHits = realisticHits_.size();
+ std::vector partialEnergies;
+ for(unsigned int hitId = 0; hitId < numberOfHits; ++hitId)
+ {
+ partialEnergies.clear();
+ std::vector removeAssociation;
+ auto& realisticHit = realisticHits_[hitId];
+ unsigned int numberOfClusters = realisticHit.hitToCluster_.size();
+ if(numberOfClusters == 1)
+ {
+ unsigned int simClusterId = realisticHit.hitToCluster_[0].simClusterId_;
+ float assignedFraction = 1.f;
+ realisticHit.hitToCluster_[0].realisticEnergyFraction_ = assignedFraction;
+ float assignedEnergy = realisticHit.totalEnergy_;
+ realisticSimClusters_[simClusterId].increaseEnergy(assignedEnergy);
+ realisticSimClusters_[simClusterId].addHitAndFraction(hitId, assignedFraction);
+ realisticSimClusters_[simClusterId].increaseExclusiveEnergy(assignedEnergy);
+ }
+ else
+ {
+ partialEnergies.resize(numberOfClusters,0.f);
+ unsigned int layer = realisticHit.layerId_;
+ float sumE = 0.f;
+ float energyDecayLength = getDecayLength(layer, fhOffset, bhOffset);
+ for(unsigned int clId = 0; clId < numberOfClusters; ++clId )
+ {
+ auto simClusterId = realisticHit.hitToCluster_[clId].simClusterId_;
+ realisticHit.hitToCluster_[clId].distanceFromMaxHit_ = XYdistanceFromMaxHit(hitId,simClusterId);
+ // partial energy is computed based on the distance from the maximum energy hit and its energy
+ // partial energy is only needed to compute a fraction and it's not the energy assigned to the cluster
+ auto maxEnergyOnLayer = realisticSimClusters_[simClusterId].getMaxEnergy(layer);
+ if(maxEnergyOnLayer>0.f)
+ {
+ partialEnergies[clId] = maxEnergyOnLayer * std::exp(-realisticHit.hitToCluster_[clId].distanceFromMaxHit_/energyDecayLength);
+ }
+ sumE += partialEnergies[clId];
+ }
+ if(sumE > 0.f)
+ {
+ float invSumE = 1.f/sumE;
+ for(unsigned int clId = 0; clId < numberOfClusters; ++clId )
+ {
+ unsigned int simClusterIndex = realisticHit.hitToCluster_[clId].simClusterId_;
+ float assignedFraction = partialEnergies[clId]*invSumE;
+ if(assignedFraction > 1e-3)
+ {
+ realisticHit.hitToCluster_[clId].realisticEnergyFraction_ = assignedFraction;
+ float assignedEnergy = assignedFraction *realisticHit.totalEnergy_;
+ realisticSimClusters_[simClusterIndex].increaseEnergy(assignedEnergy);
+ realisticSimClusters_[simClusterIndex].addHitAndFraction(hitId, assignedFraction);
+ // if the hits energy belongs for more than exclusiveFraction to a cluster, also the cluster's
+ // exclusive energy is increased. The exclusive energy will be needed to evaluate if
+ // a realistic cluster will be invisible, i.e. absorbed by other clusters
+ if( (useMCFractionsForExclEnergy and realisticHit.hitToCluster_[clId].mcEnergyFraction_ > exclusiveFraction) or
+ (!useMCFractionsForExclEnergy and assignedFraction > exclusiveFraction) )
+ {
+ realisticSimClusters_[simClusterIndex].increaseExclusiveEnergy(assignedEnergy);
+ }
+ }
+ else
+ {
+ removeAssociation.push_back(simClusterIndex);
+ }
+ }
+ }
+ }
+
+ while(!removeAssociation.empty())
+ {
+ auto clusterToRemove = removeAssociation.back();
+ removeAssociation.pop_back();
+
+ realisticHit.hitToCluster_.erase(std::remove_if(realisticHit.hitToCluster_.begin(), realisticHit.hitToCluster_.end(), [clusterToRemove](const RealisticHit::HitToCluster& x)
+ {
+ return x.simClusterId_ == clusterToRemove;
+ }), realisticHit.hitToCluster_.end());
+ }
+ }
+ }
+
+ void findAndMergeInvisibleClusters(float invisibleFraction, float exclusiveFraction)
+ {
+ unsigned int numberOfRealSimClusters = realisticSimClusters_.size();
+
+ for(unsigned int clId= 0; clId < numberOfRealSimClusters; ++clId)
+ {
+ if(realisticSimClusters_[clId].getExclusiveEnergyFraction() < invisibleFraction)
+ {
+ realisticSimClusters_[clId].setVisible(false);
+ auto& hAndF = realisticSimClusters_[clId].hitsIdsAndFractions();
+ std::unordered_map < unsigned int, float> energyInNeighbors;
+ float totalSharedEnergy=0.f;
+
+ for(auto& elt : hAndF)
+ {
+ unsigned int hitId = elt.first;
+ float fraction = elt.second;
+ auto& realisticHit = realisticHits_[hitId];
+
+ if(realisticHit.hitToCluster_.size() >1 && fraction < 1.f)
+ {
+ float correction = 1.f - fraction;
+ unsigned int numberOfClusters = realisticHit.hitToCluster_.size();
+ int clusterToRemove = -1;
+ for(unsigned int i = 0; i< numberOfClusters; ++i)
+ {
+ auto simClusterIndex = realisticHit.hitToCluster_[i].simClusterId_;
+ if(simClusterIndex == clId)
+ {
+ clusterToRemove = i;
+ }
+ else
+ if(realisticSimClusters_[simClusterIndex].isVisible())
+ {
+ float oldFraction = realisticHit.hitToCluster_[i].realisticEnergyFraction_;
+ float newFraction = oldFraction/correction;
+ float oldEnergy = oldFraction*realisticHit.totalEnergy_;
+ float newEnergy= newFraction*realisticHit.totalEnergy_;
+ float sharedEnergy = newEnergy-oldEnergy;
+ energyInNeighbors[simClusterIndex] +=sharedEnergy;
+ totalSharedEnergy +=sharedEnergy;
+ realisticSimClusters_[simClusterIndex].increaseEnergy(sharedEnergy);
+ realisticSimClusters_[simClusterIndex].modifyFractionForHitId(newFraction, hitId);
+ realisticHit.hitToCluster_[i].realisticEnergyFraction_ = newFraction;
+ if(newFraction > exclusiveFraction)
+ {
+ realisticSimClusters_[simClusterIndex].increaseExclusiveEnergy(sharedEnergy);
+ if(oldFraction <=exclusiveFraction)
+ {
+ realisticSimClusters_[simClusterIndex].increaseExclusiveEnergy(oldEnergy);
+ }
+ }
+ }
+ }
+ realisticSimClusters_[realisticHit.hitToCluster_[clusterToRemove].simClusterId_].modifyFractionForHitId(0.f, hitId);
+ realisticHit.hitToCluster_.erase(realisticHit.hitToCluster_.begin()+clusterToRemove);
+ }
+ }
+
+ for(auto& elt : hAndF)
+ {
+ unsigned int hitId = elt.first;
+ auto& realisticHit = realisticHits_[hitId];
+ if(realisticHit.hitToCluster_.size()==1 and realisticHit.hitToCluster_[0].simClusterId_ == clId and totalSharedEnergy > 0.f)
+ {
+ for (auto& pair: energyInNeighbors)
+ {
+ // hits that belonged completely to the absorbed cluster are redistributed
+ // based on the fraction of energy shared in the shared hits
+ float sharedFraction = pair.second/totalSharedEnergy;
+ float assignedEnergy = realisticHit.totalEnergy_*sharedFraction;
+ realisticSimClusters_[pair.first].increaseEnergy(assignedEnergy);
+ realisticSimClusters_[pair.first].addHitAndFraction(hitId, sharedFraction);
+ realisticHit.hitToCluster_.emplace_back(RealisticHit::HitToCluster{pair.first, 0.f, -1.f, sharedFraction});
+ if(sharedFraction > exclusiveFraction)
+ realisticSimClusters_[pair.first].increaseExclusiveEnergy(assignedEnergy);
+ }
+ }
+ }
+
+ }
+ }
+ }
+
+ void findCentersOfGravity()
+ {
+ for(auto& cluster : realisticSimClusters_)
+ {
+ if(cluster.isVisible())
+ {
+ unsigned int layersNum = cluster.getLayersNum();
+ std::vector totalEnergyPerLayer(layersNum, 0.f);
+ std::vector xEnergyPerLayer(layersNum, 0.f);
+ std::vector yEnergyPerLayer(layersNum, 0.f);
+ std::vector zPositionPerLayer(layersNum, 0.f);
+ const auto& hAndF = cluster.hitsIdsAndFractions();
+ for(auto& elt : hAndF)
+ {
+ auto hitId = elt.first;
+ auto fraction = elt.second;
+ const auto & hit = realisticHits_[hitId];
+ const auto & hitPos = hit.hitPosition_;
+ auto layerId = hit.layerId_;
+ auto hitEinCluster = hit.totalEnergy_*fraction;
+ totalEnergyPerLayer[layerId]+= hitEinCluster;
+ xEnergyPerLayer[layerId] += hitPos[0]*hitEinCluster;
+ yEnergyPerLayer[layerId] += hitPos[1]*hitEinCluster;
+ zPositionPerLayer[layerId] = hitPos[2];
+ }
+ Hit3DPosition centerOfGravity;
+ for(unsigned int layerId=0; layerId 0.f)
+ {
+ centerOfGravity = {{xEnergyPerLayer[layerId]/energyOnLayer,yEnergyPerLayer[layerId]/energyOnLayer, zPositionPerLayer[layerId] }};
+ cluster.setCenterOfGravity(layerId,centerOfGravity );
+ }
+ }
+ }
+ }
+ }
+
+ void filterHitsByDistance(float maxDistance)
+ {
+ for(auto& cluster : realisticSimClusters_)
+ {
+ if(cluster.isVisible())
+ {
+ auto& hAndF = cluster.hitsIdsAndFractions();
+ for(unsigned int i = 0; i maxDistance)
+ {
+ cluster.modifyFractionByIndex(0.f, i);
+ }
+ }
+ }
+ }
+ }
+
+ const std::vector< RealisticCluster > & realisticClusters() const
+ { return realisticSimClusters_;}
+
+ private:
+ // the vector of the Realistic SimClusters
+ std::vector< RealisticCluster > realisticSimClusters_;
+ // the vector of the Realistic SimClusters
+ std::vector< RealisticHit > realisticHits_;
+ };
+
+
+
+#endif
diff --git a/RecoParticleFlow/PFClusterProducer/plugins/SimMappers/RealisticSimClusterMapper.cc b/RecoParticleFlow/PFClusterProducer/plugins/SimMappers/RealisticSimClusterMapper.cc
new file mode 100644
index 0000000000000..0ddb4f8ec4315
--- /dev/null
+++ b/RecoParticleFlow/PFClusterProducer/plugins/SimMappers/RealisticSimClusterMapper.cc
@@ -0,0 +1,128 @@
+/////////////////////////
+// Author: Felice Pantaleo
+// Date: 30/06/2017
+// Email: felice@cern.ch
+/////////////////////////
+#include
+#include "RealisticSimClusterMapper.h"
+#include "FWCore/MessageLogger/interface/MessageLogger.h"
+
+#include "FWCore/Framework/interface/Event.h"
+
+#include "SimDataFormats/CaloAnalysis/interface/SimCluster.h"
+#include "DataFormats/ForwardDetId/interface/HGCalDetId.h"
+#include "RealisticHitToClusterAssociator.h"
+
+#ifdef PFLOW_DEBUG
+#define LOGVERB(x) edm::LogVerbatim(x)
+#define LOGWARN(x) edm::LogWarning(x)
+#define LOGERR(x) edm::LogError(x)
+#define LOGDRESSED(x) edm::LogInfo(x)
+#else
+#define LOGVERB(x) LogTrace(x)
+#define LOGWARN(x) edm::LogWarning(x)
+#define LOGERR(x) edm::LogError(x)
+#define LOGDRESSED(x) LogDebug(x)
+#endif
+
+void RealisticSimClusterMapper::updateEvent(const edm::Event& ev)
+{
+ ev.getByToken(simClusterToken_, simClusterH_);
+}
+
+void RealisticSimClusterMapper::update(const edm::EventSetup& es)
+{
+ rhtools_.getEventSetup(es);
+
+}
+
+void RealisticSimClusterMapper::buildClusters(const edm::Handle& input,
+ const std::vector& rechitMask, const std::vector& seedable,
+ reco::PFClusterCollection& output)
+{
+ const SimClusterCollection& simClusters = *simClusterH_;
+ auto const& hits = *input;
+ RealisticHitToClusterAssociator realisticAssociator;
+ const int numberOfLayers = rhtools_.getLayer(ForwardSubdetector::ForwardEmpty);
+ realisticAssociator.init(hits.size(), simClusters.size(), numberOfLayers + 1);
+ // for quick indexing back to hit energy
+ std::unordered_map < uint32_t, size_t > detIdToIndex(hits.size());
+ for (uint32_t i = 0; i < hits.size(); ++i)
+ {
+ detIdToIndex[hits[i].detId()] = i;
+ auto ref = makeRefhit(input, i);
+ const auto& hitPos = rhtools_.getPosition(ref->detId());
+
+ realisticAssociator.insertHitPosition(hitPos.x(), hitPos.y(), hitPos.z(), i);
+ realisticAssociator.insertHitEnergy(ref->energy(), i);
+ realisticAssociator.insertLayerId(rhtools_.getLayerWithOffset(ref->detId()), i);
+
+ }
+
+ for (unsigned int ic = 0; ic < simClusters.size(); ++ic)
+ {
+ const auto & sc = simClusters[ic];
+ const auto& hitsAndFractions = sc.hits_and_fractions();
+ for (const auto& hAndF : hitsAndFractions)
+ {
+ auto itr = detIdToIndex.find(hAndF.first);
+ if (itr == detIdToIndex.end())
+ {
+ continue; // hit wasn't saved in reco or did not pass the SNR threshold
+ }
+ auto hitId = itr->second;
+ auto ref = makeRefhit(input, hitId);
+ float fraction = hAndF.second;
+ float associatedEnergy = fraction * ref->energy();
+ realisticAssociator.insertSimClusterIdAndFraction(ic, fraction, hitId,
+ associatedEnergy);
+ }
+ }
+ realisticAssociator.computeAssociation(exclusiveFraction_, useMCFractionsForExclEnergy_,
+ rhtools_.lastLayerEE(), rhtools_.lastLayerFH());
+ realisticAssociator.findAndMergeInvisibleClusters(invisibleFraction_, exclusiveFraction_);
+ realisticAssociator.findCentersOfGravity();
+ if(maxDistanceFilter_)
+ realisticAssociator.filterHitsByDistance(maxDistance_);
+
+ const auto& realisticClusters = realisticAssociator.realisticClusters();
+ unsigned int nClusters = realisticClusters.size();
+ for (unsigned ic = 0; ic < nClusters; ++ic)
+ {
+ float highest_energy = 0.0f;
+ output.emplace_back();
+ reco::PFCluster& back = output.back();
+ edm::Ref < std::vector > seed;
+ if (realisticClusters[ic].isVisible())
+ {
+ const auto& hitsIdsAndFractions = realisticClusters[ic].hitsIdsAndFractions();
+ for (const auto& idAndF : hitsIdsAndFractions)
+ {
+ auto fraction = idAndF.second;
+ if (fraction > 0.f)
+ {
+ auto ref = makeRefhit(input, idAndF.first);
+ back.addRecHitFraction(reco::PFRecHitFraction(ref, fraction));
+ const float hit_energy = fraction * ref->energy();
+ if (hit_energy > highest_energy || highest_energy == 0.0)
+ {
+ highest_energy = hit_energy;
+ seed = ref;
+ }
+ }
+ }
+ }
+ if (back.hitsAndFractions().size() != 0)
+ {
+ back.setSeed(seed->detId());
+ back.setEnergy(realisticClusters[ic].getEnergy());
+ back.setCorrectedEnergy(realisticClusters[ic].getEnergy());
+ }
+ else
+ {
+ back.setSeed(-1);
+ back.setEnergy(0.f);
+ }
+ }
+}
+
diff --git a/RecoParticleFlow/PFClusterProducer/plugins/SimMappers/RealisticSimClusterMapper.h b/RecoParticleFlow/PFClusterProducer/plugins/SimMappers/RealisticSimClusterMapper.h
new file mode 100644
index 0000000000000..ce8024ae8b232
--- /dev/null
+++ b/RecoParticleFlow/PFClusterProducer/plugins/SimMappers/RealisticSimClusterMapper.h
@@ -0,0 +1,55 @@
+#ifndef __RecoParticleFlow_PFClusterProducer_RealisticSimClusterMapper_H__
+#define __RecoParticleFlow_PFClusterProducer_RealisticSimClusterMapper_H__
+/////////////////////////
+// Author: Felice Pantaleo
+// Date: 30/06/2017
+// Email: felice@cern.ch
+/////////////////////////
+#include "RecoParticleFlow/PFClusterProducer/interface/InitialClusteringStepBase.h"
+#include "DataFormats/ParticleFlowReco/interface/PFRecHitFraction.h"
+#include "RecoLocalCalo/HGCalRecAlgos/interface/RecHitTools.h"
+
+#include "SimDataFormats/CaloAnalysis/interface/SimClusterFwd.h"
+
+class RealisticSimClusterMapper : public InitialClusteringStepBase {
+ public:
+ RealisticSimClusterMapper(const edm::ParameterSet& conf,
+ edm::ConsumesCollector& sumes) :
+ InitialClusteringStepBase(conf,sumes),
+ invisibleFraction_(conf.getParameter("invisibleFraction")),
+ exclusiveFraction_(conf.getParameter("exclusiveFraction")),
+ maxDistanceFilter_(conf.getParameter("maxDistanceFilter")),
+ maxDistance_(conf.getParameter("maxDistance")),
+ useMCFractionsForExclEnergy_(conf.getParameter("useMCFractionsForExclEnergy"))
+ {
+ simClusterToken_ = sumes.consumes(conf.getParameter("simClusterSrc"));
+ }
+ virtual ~RealisticSimClusterMapper() {}
+ RealisticSimClusterMapper(const RealisticSimClusterMapper&) = delete;
+ RealisticSimClusterMapper& operator=(const RealisticSimClusterMapper&) = delete;
+
+ virtual void updateEvent(const edm::Event&) override final;
+ virtual void update(const edm::EventSetup&) override final;
+
+ void buildClusters(const edm::Handle&,
+ const std::vector&,
+ const std::vector&,
+ reco::PFClusterCollection&) override;
+
+ private:
+ hgcal::RecHitTools rhtools_;
+ const float invisibleFraction_ = 0.3f;
+ const float exclusiveFraction_ = 0.7f;
+ const bool maxDistanceFilter_ = false;
+ const float maxDistance_ = 10.f;
+ const bool useMCFractionsForExclEnergy_ = false;
+ edm::EDGetTokenT simClusterToken_;
+ edm::Handle simClusterH_;
+
+};
+
+DEFINE_EDM_PLUGIN(InitialClusteringStepFactory,
+ RealisticSimClusterMapper,
+ "RealisticSimClusterMapper");
+
+#endif
diff --git a/RecoParticleFlow/PFClusterProducer/python/particleFlowClusterHGC_cfi.py b/RecoParticleFlow/PFClusterProducer/python/particleFlowClusterHGC_cfi.py
index 784e58e02775e..781af07c71167 100644
--- a/RecoParticleFlow/PFClusterProducer/python/particleFlowClusterHGC_cfi.py
+++ b/RecoParticleFlow/PFClusterProducer/python/particleFlowClusterHGC_cfi.py
@@ -14,12 +14,19 @@
# initial step clusterizer
_simClusterMapper_HGCal = cms.PSet(
- algoName = cms.string("GenericSimClusterMapper"),
+ algoName = cms.string("RealisticSimClusterMapper"),
+ exclusiveFraction = cms.double(0.6),
+ invisibleFraction = cms.double(0.6),
+ maxDistanceFilter = cms.bool(True),
+ #filtering out hits outside a cylinder of 10cm radius, built around the center of gravity per each layer
+ maxDistance = cms.double(10.0),
+ useMCFractionsForExclEnergy = cms.bool(False),
thresholdsByDetector = cms.VPSet(
),
simClusterSrc = cms.InputTag("mix:MergedCaloTruth")
)
+
#position calculations
_positionCalcPCA_HGCal = cms.PSet(
algoName = cms.string("Cluster3DPCACalculator"),
diff --git a/RecoParticleFlow/PFClusterProducer/python/particleFlowRecHitHGC_cfi.py b/RecoParticleFlow/PFClusterProducer/python/particleFlowRecHitHGC_cfi.py
index d6f0dc2142f83..680f1213357dd 100644
--- a/RecoParticleFlow/PFClusterProducer/python/particleFlowRecHitHGC_cfi.py
+++ b/RecoParticleFlow/PFClusterProducer/python/particleFlowRecHitHGC_cfi.py
@@ -24,10 +24,10 @@
qualityTests = cms.VPSet(
# Enabling PFRecHitQTestHGCalThresholdSNR will filter out of the PFRecHits, all the HGCRecHits with energy not exceeding
# 5 sigma noise
-# cms.PSet(
-# name = cms.string("PFRecHitQTestHGCalThresholdSNR"),
-# thresholdSNR = cms.double(5.0),
-# ),
+ cms.PSet(
+ name = cms.string("PFRecHitQTestHGCalThresholdSNR"),
+ thresholdSNR = cms.double(5.0),
+ ),
)
),
cms.PSet(
@@ -37,10 +37,10 @@
qualityTests = cms.VPSet(
# Enabling PFRecHitQTestHGCalThresholdSNR will filter out of the PFRecHits, all the HGCRecHits with energy not exceeding
# 5 sigma noise
-# cms.PSet(
-# name = cms.string("PFRecHitQTestHGCalThresholdSNR"),
-# thresholdSNR = cms.double(5.0),
-# ),
+ cms.PSet(
+ name = cms.string("PFRecHitQTestHGCalThresholdSNR"),
+ thresholdSNR = cms.double(5.0),
+ ),
)
),
cms.PSet(
@@ -50,10 +50,10 @@
qualityTests = cms.VPSet(
# Enabling PFRecHitQTestHGCalThresholdSNR will filter out of the PFRecHits, all the HGCRecHits with energy not exceeding
# 5 sigma noise
-# cms.PSet(
-# name = cms.string("PFRecHitQTestHGCalThresholdSNR"),
-# thresholdSNR = cms.double(5.0),
-# ),
+ cms.PSet(
+ name = cms.string("PFRecHitQTestHGCalThresholdSNR"),
+ thresholdSNR = cms.double(5.0),
+ ),
)
)
)