CMS 3D CMS Logo

EGammaSuperclusterProducer.cc
Go to the documentation of this file.
1 // Authors : Theo Cuisset <theo.cuisset@cern.ch>, Shamik Ghosh <shamik.ghosh@cern.ch>
2 // Date : 01/2024
3 /*
4 Translates TICL superclusters to ECAL supercluster dataformats (reco::SuperCluster and reco::CaloCluster).
5 Performs similar task as RecoEcal/EgammaCLusterProducers/PFECALSuperClusterProducer
6 Note that all tracksters are translated to reco::CaloCluster, even those that are not in any SuperCluster
7 */
8 
18 
19 #include <vector>
20 #include <array>
21 #include <limits>
22 #include <algorithm>
23 
25 
32 
34 
35 class EGammaSuperclusterProducer : public edm::stream::EDProducer<edm::GlobalCache<ONNXRuntime>> {
36 public:
38 
39  void produce(edm::Event&, const edm::EventSetup&) override;
40 
41  static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
42 
43  static std::unique_ptr<ONNXRuntime> initializeGlobalCache(const edm::ParameterSet& iConfig);
44  static void globalEndJob(const ONNXRuntime*);
45 
46 private:
53 };
54 
56  : ticlSuperClustersToken_(consumes<ticl::TracksterCollection>(ps.getParameter<edm::InputTag>("ticlSuperClusters"))),
57  superClusterLinksToken_(consumes<std::vector<std::vector<unsigned int>>>(
58  edm::InputTag(ps.getParameter<edm::InputTag>("ticlSuperClusters").label(),
59  "linkedTracksterIdToInputTracksterId",
60  ps.getParameter<edm::InputTag>("ticlSuperClusters").process()))),
61  ticlTrackstersEMToken_(consumes<ticl::TracksterCollection>(ps.getParameter<edm::InputTag>("ticlTrackstersEM"))),
62  layerClustersToken_(consumes<reco::CaloClusterCollection>(ps.getParameter<edm::InputTag>("layerClusters"))),
63  superclusterEtThreshold_(ps.getParameter<double>("superclusterEtThreshold")),
64  enableRegression_(ps.getParameter<bool>("enableRegression")) {
65  produces<reco::SuperClusterCollection>();
66  produces<reco::CaloClusterCollection>(); // The CaloCluster corresponding to each EM trackster
67 }
68 
70  auto const& ticlSuperclusters = iEvent.get(ticlSuperClustersToken_);
71  auto const& ticlSuperclusterLinks = iEvent.get(superClusterLinksToken_);
72  auto emTracksters_h = iEvent.getHandle(ticlTrackstersEMToken_);
73  auto const& emTracksters = *emTracksters_h;
74  auto const& layerClusters = iEvent.get(layerClustersToken_);
75  // Output collections :
76  auto egammaSuperclusters = std::make_unique<reco::SuperClusterCollection>();
77  auto caloClustersEM = std::make_unique<reco::CaloClusterCollection>();
78 
79  // Fill reco::CaloCluster collection (1-1 mapping to TICL EM tracksters)
80  for (ticl::Trackster const& emTrackster : emTracksters) {
81  std::vector<std::pair<DetId, float>> hitsAndFractions;
82  int iLC = 0;
83  std::for_each(std::begin(emTrackster.vertices()), std::end(emTrackster.vertices()), [&](unsigned int lcId) {
84  const auto fraction = 1.f / emTrackster.vertex_multiplicity(iLC++);
85  for (const auto& cell : layerClusters[lcId].hitsAndFractions()) {
86  hitsAndFractions.emplace_back(cell.first, cell.second * fraction);
87  }
88  });
89 
90  reco::CaloCluster& caloCluster = caloClustersEM->emplace_back(
91  emTrackster.raw_energy(), // energy
92  math::XYZPoint(emTrackster.barycenter()), // position
94  hitsAndFractions,
95  reco::CaloCluster::particleFlow, // algoID (copying from output of PFECALCSuperClusterProducer)
96  hitsAndFractions.at(0)
97  .first // seedId (this may need to be updated once a common definition of the seed of a cluster is adopted for Phase-2)
98  );
99  caloCluster.setCorrectedEnergy(emTrackster.raw_energy()); // Needs to be updated with new supercluster regression
100  }
101 
102  edm::OrphanHandle<reco::CaloClusterCollection> caloClustersEM_h = iEvent.put(std::move(caloClustersEM));
103 
104  // Fill reco::SuperCluster collection and prepare regression inputs
105  assert(ticlSuperclusters.size() == ticlSuperclusterLinks.size());
106  const unsigned int regressionFeatureCount = 8;
107  std::vector<float> regressionInputs;
108  regressionInputs.reserve(ticlSuperclusters.size() * regressionFeatureCount);
109  unsigned int superclustersPassingSelectionsCount = 0;
110  for (std::size_t sc_i = 0; sc_i < ticlSuperclusters.size(); sc_i++) {
111  ticl::Trackster const& ticlSupercluster = ticlSuperclusters[sc_i];
112  if (ticlSupercluster.raw_pt() < superclusterEtThreshold_)
113  continue;
114  std::vector<unsigned int> const& superclusterLink = ticlSuperclusterLinks[sc_i];
115  assert(!superclusterLink.empty());
116 
117  reco::CaloClusterPtrVector trackstersEMInSupercluster;
119  float max_phi = std::numeric_limits<float>::min();
121  float min_phi = std::numeric_limits<float>::max();
122  for (unsigned int tsInSc_id : superclusterLink) {
123  trackstersEMInSupercluster.push_back(reco::CaloClusterPtr(caloClustersEM_h, tsInSc_id));
124  ticl::Trackster const& constituentTrackster = emTracksters[tsInSc_id];
125  max_eta = std::max(constituentTrackster.barycenter().eta(), max_eta);
126  max_phi = std::max(constituentTrackster.barycenter().phi(), max_phi);
127  min_eta = std::min(constituentTrackster.barycenter().eta(), min_eta);
128  min_phi = std::min(constituentTrackster.barycenter().phi(), min_phi);
129  }
130  egammaSuperclusters->emplace_back(
131  ticlSupercluster.raw_energy(),
132  reco::SuperCluster::Point(ticlSupercluster.barycenter()),
133  reco::CaloClusterPtr(caloClustersEM_h,
134  superclusterLink[0]), // seed (first trackster in superclusterLink is the seed)
135  trackstersEMInSupercluster, // clusters
136  0., // Epreshower (not relevant for HGCAL)
137  -1, // phiwidth (not implemented yet)
138  -1 // etawidth (not implemented yet)
139  );
140  superclustersPassingSelectionsCount++;
141 
142  if (enableRegression_) {
143  regressionInputs.insert(
144  regressionInputs.end(),
145  {ticlSupercluster.barycenter().eta(),
146  ticlSupercluster.barycenter().phi(),
147  ticlSupercluster.raw_energy(),
149  max_phi - min_phi > M_PI ? 2 * static_cast<float>(M_PI) - (max_phi - min_phi) : max_phi - min_phi,
150  emTracksters[superclusterLink[0]].raw_energy() -
151  (superclusterLink.size() >= 2 ? emTracksters[superclusterLink.back()].raw_energy() : 0.f),
152  emTracksters[superclusterLink[0]].raw_energy() / ticlSupercluster.raw_energy(),
153  static_cast<float>(superclusterLink.size())});
154  }
155  }
156 
157  if (enableRegression_ && superclustersPassingSelectionsCount > 0) {
158  // Run the regression
159  // ONNXRuntime takes std::vector<std::vector<float>>& as input (non-const reference) so we have to make a new vector
160  std::vector<std::vector<float>> inputs_for_onnx{{std::move(regressionInputs)}};
161  std::vector<float> outputs =
162  globalCache()->run({"input"}, inputs_for_onnx, {}, {}, superclustersPassingSelectionsCount)[0];
163 
164  assert(egammaSuperclusters->size() == outputs.size());
165  for (std::size_t sc_i = 0; sc_i < egammaSuperclusters->size(); sc_i++) {
166  (*egammaSuperclusters)[sc_i].setCorrectedEnergy(outputs[sc_i]);
167  // correctedEnergyUncertainty is left at its default value
168  }
169  }
170 
171  iEvent.put(std::move(egammaSuperclusters));
172 }
173 
174 std::unique_ptr<ONNXRuntime> EGammaSuperclusterProducer::initializeGlobalCache(const edm::ParameterSet& iConfig) {
175  if (iConfig.getParameter<bool>("enableRegression"))
176  return std::make_unique<ONNXRuntime>(iConfig.getParameter<edm::FileInPath>("regressionModelPath").fullPath());
177  else
178  return std::unique_ptr<ONNXRuntime>(nullptr);
179 }
180 
182 
185  desc.add<edm::InputTag>("ticlSuperClusters", edm::InputTag("ticlTracksterLinksSuperclusteringDNN"));
186  desc.add<edm::InputTag>("ticlTrackstersEM", edm::InputTag("ticlTrackstersCLUE3DHigh"))
187  ->setComment("The trackster collection used before superclustering, ie CLUE3D EM tracksters");
188  desc.add<edm::InputTag>("layerClusters", edm::InputTag("hgcalMergeLayerClusters"))
189  ->setComment("The layer cluster collection that goes with ticlTrackstersEM");
190  desc.add<double>("superclusterEtThreshold", 4.)->setComment("Minimum supercluster transverse energy.");
191  desc.add<bool>("enableRegression", true)->setComment("Enable supercluster energy regression");
192  desc.add<edm::FileInPath>("regressionModelPath",
193  edm::FileInPath("RecoHGCal/TICL/data/superclustering/regression_v1.onnx"))
194  ->setComment("Path to regression network (as ONNX model)");
195 
196  descriptions.add("ticlEGammaSuperClusterProducer", desc);
197 }
198 
T getParameter(std::string const &) const
Definition: ParameterSet.h:307
const float raw_pt() const
Definition: Trackster.h:156
const Vector & barycenter() const
Definition: Trackster.h:159
edm::EDGetTokenT< ticl::TracksterCollection > ticlSuperClustersToken_
assert(be >=bs)
void produce(edm::Event &, const edm::EventSetup &) override
char const * label
edm::EDGetTokenT< reco::CaloClusterCollection > layerClustersToken_
int iEvent
Definition: GenABIO.cc:224
void setCorrectedEnergy(double cenergy)
Definition: CaloCluster.h:137
const float raw_energy() const
Definition: Trackster.h:154
edm::EDGetTokenT< ticl::TracksterCollection > ticlTrackstersEMToken_
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
static std::unique_ptr< ONNXRuntime > initializeGlobalCache(const edm::ParameterSet &iConfig)
std::vector< CaloCluster > CaloClusterCollection
collection of CaloCluster objects
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
#define M_PI
XYZPointD XYZPoint
point in space with cartesian internal representation
Definition: Point3D.h:12
void add(std::string const &label, ParameterSetDescription const &psetDescription)
math::XYZPoint Point
Definition: SuperCluster.h:22
fixed size matrix
HLT enums.
Definition: Common.h:10
std::vector< Trackster > TracksterCollection
Definition: Trackster.h:254
edm::EDGetTokenT< std::vector< std::vector< unsigned int > > > superClusterLinksToken_
EGammaSuperclusterProducer(const edm::ParameterSet &, const ONNXRuntime *)
static void globalEndJob(const ONNXRuntime *)
def move(src, dest)
Definition: eostools.py:511
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)