ATLAS Offline Software
JetClusterer.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #include <memory>
7 #include "JetRec/JetClusterer.h"
8 #include "fastjet/PseudoJet.hh"
9 #include "fastjet/ClusterSequence.hh"
10 #include "fastjet/ClusterSequenceArea.hh"
11 #include "fastjet/config.h"
12 #include "fastjet/contrib/VariableRPlugin.hh"
13 
15 #include "xAODJet/JetContainer.h"
17 
18 #include "JetEDM/FastJetUtils.h"
19 
23 
24 namespace JetClustererHelper
25 {
26 
27  void seedsFromEventInfo(const xAOD::EventInfo *ei, std::vector<int> &seeds)
28  {
29  // const xAOD::EventInfo* pevinfo = handle.cptr();
30  auto ievt = ei->eventNumber();
31  auto irun = ei->runNumber();
32 
34  {
35  // For MC, use the channel and MC event number
36  ievt = ei->mcEventNumber();
37  irun = ei->mcChannelNumber();
38  }
39  seeds.push_back(ievt);
40  seeds.push_back(irun);
41  }
42 }
43 
45 {
46 
47  ATH_MSG_DEBUG("Initializing...");
51  {
52  ATH_MSG_ERROR("Invalid jet algorithm name: " << m_jetalg);
53  ATH_MSG_ERROR("Allowed values are Kt, CamKt, AntiKt, etc.");
54  return StatusCode::FAILURE;
55  }
56  if (m_jetrad <= 0)
57  {
58  ATH_MSG_ERROR("Invalid jet size parameter: " << m_jetrad);
59  return StatusCode::FAILURE;
60  }
61 
62  // buld an empty ClusterSequence, just for the fastjet splash screen to appear during initialization (?)
63  fastjet::JetDefinition jetdef(m_fjalg, m_jetrad);
64  m_useArea = m_ghostarea > 0;
65 
67  fastjet::ClusterSequence cs(empty, jetdef);
68  cs.inclusive_jets(m_ptmin);
69  m_isVariableR = m_minrad >= 0.0 && m_massscale >= 0.0;
70 
71  // Input DataHandles
72  if (!m_finalPseudoJets.empty())
73  {
74  ATH_MSG_WARNING("A non-empty value was found for the FinalPseudoJets WriteHandleKey -- this will be ignored!");
75  }
76 
79  m_finalPseudoJets = name() + "FinalPJ";
81  m_clusterSequence = name() + "ClusterSequence";
83 
85 
86  return StatusCode::SUCCESS;
87 }
88 
89 // -----------------------
90 // Build the cluster sequence
91 std::unique_ptr<fastjet::ClusterSequence> JetClusterer::buildClusterSequence(const PseudoJetVector *pseudoJetVector) const
92 {
93 
94  fastjet::JetDefinition jetdef(m_fjalg, m_jetrad);
95  using fastjet::contrib::VariableRPlugin;
96  std::unique_ptr<VariableRPlugin> VRJetPlugin(nullptr);
97 
98  if (m_isVariableR)
99  {
100  /* clustering algorithm
101  * They correspond to p parameter of Sequential recombination algs
102  * AKTLIKE = -1, CALIKE = 0, KTLIKE = 1
103  */
104  VariableRPlugin::ClusterType VRClusterType = VariableRPlugin::AKTLIKE;
105  switch (m_fjalg)
106  {
108  VRClusterType = VariableRPlugin::KTLIKE;
109  break;
111  VRClusterType = VariableRPlugin::AKTLIKE;
112  break;
114  VRClusterType = VariableRPlugin::CALIKE;
115  break;
116  default:
117  ATH_MSG_ERROR("Unsupported clustering algorithm for Variable-R jet finding.");
118  return nullptr;
119  }
120  VRJetPlugin = std::make_unique<VariableRPlugin>(m_massscale, m_minrad, m_jetrad, VRClusterType, false);
121  jetdef = fastjet::JetDefinition(VRJetPlugin.get());
122  }
123 
124  std::unique_ptr<fastjet::ClusterSequence> clSequence(nullptr);
125 
126  if (m_useArea)
127  {
128  // Prepare ghost area specifications -------------
129  ATH_MSG_DEBUG("Creating input area cluster sequence");
130  bool seedsok = true;
131  fastjet::AreaDefinition adef = buildAreaDefinition(seedsok);
132 
133  if (seedsok)
134  {
135  clSequence = std::make_unique<fastjet::ClusterSequenceArea>(*pseudoJetVector, jetdef, adef);
136  }
137  else
138  {
139  return nullptr;
140  }
141  }
142  else
143  {
144  ATH_MSG_DEBUG("Creating input cluster sequence");
145  clSequence = std::make_unique<fastjet::ClusterSequence>(*pseudoJetVector, jetdef);
146  }
147 
148  return clSequence;
149 }
150 
151 void JetClusterer::processPseudoJet(const fastjet::PseudoJet &pj, const PseudoJetContainer &pjCont, xAOD::JetContainer *jets, const xAOD::Vertex *originVertex) const
152 {
153 
154  // -------------------------------------
155  // translate to xAOD::Jet
156  ATH_MSG_DEBUG("Converting pseudojets to xAOD::Jet");
157  static const SG::AuxElement::Accessor<const fastjet::PseudoJet *> pjAccessor("PseudoJet");
158  PseudoJetTranslator pjTranslator(m_useArea, m_useArea);
159 
160  // create the xAOD::Jet from the PseudoJet, doing the signal & constituents extraction
161  xAOD::Jet &jet = pjTranslator.translate(pj, pjCont, *jets, originVertex);
162 
163  // Add the PseudoJet onto the xAOD jet. Maybe we should do it in the above JetFromPseudojet call ??
164  pjAccessor(jet) = &pj;
165 
166  jet.setInputType(xAOD::JetInput::Type(m_inputType.value()));
168  jet.setAlgorithmType(ialg);
169  jet.setSizeParameter(m_jetrad.value());
170  if (m_isVariableR)
171  {
172  jet.setAttribute(xAOD::JetAttribute::VariableRMinRadius, m_minrad.value());
174  }
175  if (m_useArea)
176  jet.setAttribute(xAOD::JetAttribute::JetGhostArea, m_ghostarea.value());
177 
178  ATH_MSG_VERBOSE(" xAOD::Jet with pt " << std::setprecision(4) << jet.pt() * 1e-3 << " has " << jet.getConstituents().size() << " constituents");
179  ATH_MSG_VERBOSE(" Leading constituent is of type " << jet.getConstituents()[0].rawConstituent()->type());
180 
181  // Perhaps better to make configurable
182  if (originVertex)
183  {
184  jet.setAssociatedObject("OriginVertex", originVertex);
185  }
186  else
187  {
188  ATH_MSG_VERBOSE("Could not set OriginVertex for jet!");
189  }
190 }
191 
192 std::pair<std::unique_ptr<xAOD::JetContainer>, std::unique_ptr<SG::IAuxStore>> JetClusterer::getJets() const
193 {
194  // Return this in case of any problems
195  auto nullreturn = std::make_pair(std::unique_ptr<xAOD::JetContainer>(nullptr), std::unique_ptr<SG::IAuxStore>(nullptr));
196 
197  // -----------------------
198  // retrieve input
200  if (!pjContHandle.isValid())
201  {
202  ATH_MSG_ERROR("No valid PseudoJetContainer with key " << m_inputPseudoJets.key());
203  return nullreturn;
204  }
205 
206  // Build the container to be returned
207  // Avoid memory leaks with unique_ptr
208  auto jets = std::make_unique<xAOD::JetContainer>();
209  auto auxCont = std::make_unique<xAOD::JetAuxContainer>();
210  jets->setStore(auxCont.get());
211 
212  const PseudoJetVector *pseudoJetVector = pjContHandle->casVectorPseudoJet();
213  ATH_MSG_DEBUG("Pseudojet input container has size " << pseudoJetVector->size());
214 
215  std::unique_ptr<fastjet::ClusterSequence> clSequence = buildClusterSequence(pseudoJetVector);
216 
217  if (!clSequence)
218  return nullreturn;
219 
220  // -----------------------
221  // Build a new pointer to a PseudoJetVector containing the final PseudoJet
222  // This allows us to own the vector of PseudoJet which we will put in the evt store.
223  // Thus the contained PseudoJet will be kept frozen there and we can safely use pointer to them from the xAOD::Jet objects
224  auto pjVector = std::make_unique<PseudoJetVector>(fastjet::sorted_by_pt(clSequence->inclusive_jets(m_ptmin)));
225  ATH_MSG_DEBUG("Found jet count: " << pjVector->size());
226  if (msgLvl(MSG::VERBOSE))
227  {
228  for (const auto &pj : *pjVector)
229  {
230  msg() << " Pseudojet with pt " << std::setprecision(4) << pj.Et() * 1e-3 << " has " << pj.constituents().size() << " constituents" << endmsg;
231  }
232  }
233 
234  // No PseudoJets, so there's nothing else to do
235  // Delete the cluster sequence before we go
236  if (!pjVector->empty())
237  {
238 
239  for (const fastjet::PseudoJet &pj : *pjVector)
240  {
241  processPseudoJet(pj, *pjContHandle, jets.get(), nullptr);
242  // we want the rank to start with zero, but this is after the
243  // jet has been added, thus the "size() - 1" here.
244  m_jetRankAccessor(*jets.get()->back()) = jets->size() - 1;
245  }
246 
247  // -------------------------------------
248  // record final PseudoJetVector
250  if (!pjVectorHandle.record(std::move(pjVector)))
251  {
252  ATH_MSG_ERROR("Can't record PseudoJetVector under key " << m_finalPseudoJets);
253  return nullreturn;
254  }
255  // -------------------------------------
256  // record ClusterSequence
258  if (!clusterSeqHandle.record(std::move(clSequence)))
259  {
260  ATH_MSG_ERROR("Can't record ClusterSequence under key " << m_clusterSequence);
261  return nullreturn;
262  }
263  }
264 
265  ATH_MSG_DEBUG("Reconstructed jet count: " << jets->size() << " clusterseq=" << clSequence.get());
266  // Return the jet container and aux, use move to transfer
267  // ownership of pointers to caller
268  return std::make_pair(std::move(jets), std::move(auxCont));
269 }
270 
271 fastjet::AreaDefinition JetClusterer::buildAreaDefinition(bool &seedsok) const
272 {
273 
274  fastjet::GhostedAreaSpec gspec(5.0, 1, m_ghostarea);
275  seedsok = true;
276  std::vector<int> seeds;
277 
278  if (m_ranopt == 1)
279  {
280  // Use run/event number as random number seeds.
281  auto evtInfoHandle = SG::makeHandle(m_eventinfokey);
282  if (!evtInfoHandle.isValid())
283  {
284  ATH_MSG_ERROR("Unable to retrieve event info");
285  seedsok = false;
286  return {};
287  }
288 
289  JetClustererHelper::seedsFromEventInfo(evtInfoHandle.cptr(), seeds);
290  }
291 
292  ATH_MSG_DEBUG("Active area specs:");
293  ATH_MSG_DEBUG(" Requested ghost area: " << m_ghostarea);
294  ATH_MSG_DEBUG(" Actual ghost area: " << gspec.actual_ghost_area());
295  ATH_MSG_DEBUG(" Max eta: " << gspec.ghost_etamax());
296  ATH_MSG_DEBUG(" # ghosts: " << gspec.n_ghosts());
297  ATH_MSG_DEBUG(" # rapidity bins: " << gspec.nrap());
298  ATH_MSG_DEBUG(" # phi bins: " << gspec.nphi());
299 
300  if (seeds.size() == 2)
301  {
302  ATH_MSG_DEBUG(" Random seeds: " << seeds[0] << ", " << seeds[1]);
303  }
304  else
305  {
306  ATH_MSG_WARNING("Random generator size is not 2: " << seeds.size());
307  ATH_MSG_DEBUG(" Random seeds: ");
308  for (auto seed : seeds)
309  ATH_MSG_DEBUG(" " << seed);
310  }
311 
312  // We use with_fixed_seed() as recommended for thread safety in
313  // fastjet 3.4.0.
314  return fastjet::AreaDefinition(fastjet::active_area,
315  gspec)
316  .with_fixed_seed(seeds);
317 }
JetClusterer::m_eventinfokey
SG::ReadHandleKey< xAOD::EventInfo > m_eventinfokey
Handle to EventInfo. This is used to get the evt&run number to set the Ghost area random seeds.
Definition: JetClusterer.h:84
JetClusterer::m_jetalg
Gaudi::Property< std::string > m_jetalg
Definition: JetClusterer.h:95
VertexIndexedConstituentUserInfo.h
xAOD::EventInfo_v1::eventNumber
uint64_t eventNumber() const
The current event's event number.
xAOD::JetAlgorithmType::kt_algorithm
@ kt_algorithm
Definition: JetContainerInfo.h:31
SG::Accessor
Helper class to provide type-safe access to aux data.
Definition: Control/AthContainers/AthContainers/Accessor.h:66
JetClusterer::m_ghostarea
Gaudi::Property< float > m_ghostarea
Definition: JetClusterer.h:98
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:70
JetClustererHelper
Definition: JetClusterer.h:109
xAOD::JetAttribute::VariableRMassScale
@ VariableRMassScale
Definition: JetAttributes.h:208
JetClusterer::m_inputType
Gaudi::Property< int > m_inputType
Definition: JetClusterer.h:101
JetClusterer::m_ranopt
Gaudi::Property< int > m_ranopt
Definition: JetClusterer.h:99
xAOD::JetAttribute::VariableRMinRadius
@ VariableRMinRadius
Definition: JetAttributes.h:207
JetClusterer::m_jetrad
Gaudi::Property< float > m_jetrad
Definition: JetClusterer.h:96
AthCommonMsg< AlgTool >::msgLvl
bool msgLvl(const MSG::Level lvl) const
Definition: AthCommonMsg.h:30
xAOD::JetAttribute::JetGhostArea
@ JetGhostArea
Definition: JetAttributes.h:41
JetClusterer::m_clusterSequence
SG::WriteHandleKey< jet::ClusterSequence > m_clusterSequence
Definition: JetClusterer.h:91
PseudoJetContainer
Definition: PseudoJetContainer.h:48
JetClusterer::m_massscale
Gaudi::Property< float > m_massscale
Definition: JetClusterer.h:109
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
SG::VarHandleKey::key
const std::string & key() const
Return the StoreGate ID for the referenced object.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:141
SG::VarHandleKey::empty
bool empty() const
Test if the key is blank.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:150
xAOD::EventInfo_v1::IS_SIMULATION
@ IS_SIMULATION
true: simulation, false: data
Definition: EventInfo_v1.h:151
empty
bool empty(TH1 *h)
Definition: computils.cxx:294
xAOD::EventInfo_v1::runNumber
uint32_t runNumber() const
The current event's run number.
xAOD::EventInfo_v1::mcChannelNumber
uint32_t mcChannelNumber() const
The MC generator's channel number.
SG::makeHandle
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
Definition: ReadCondHandle.h:269
JetClusterer::m_isVariableR
bool m_isVariableR
Definition: JetClusterer.h:110
JetClusterer::buildAreaDefinition
fastjet::AreaDefinition buildAreaDefinition(bool &seedsok) const
Build the area definition when running with area calculation. The seedsok flag is set to false when e...
Definition: JetClusterer.cxx:271
JetClusterer::m_fjalg
fastjet::JetAlgorithm m_fjalg
Definition: JetClusterer.h:105
JetClusterer::initialize
StatusCode initialize() override
Dummy implementation of the initialisation function.
Definition: JetClusterer.cxx:44
PseudoJetTranslator
Definition: PseudoJetTranslator.h:12
jet
Definition: JetCalibTools_PlotJESFactors.cxx:23
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
JetClusterer::m_inputPseudoJets
SG::ReadHandleKey< PseudoJetContainer > m_inputPseudoJets
Handle Input PseudoJetContainer.
Definition: JetClusterer.h:87
PseudoJetTranslator.h
xAOD::JetAlgorithmType::fastJetDef
fastjet::JetAlgorithm fastJetDef(ID id)
Definition: FastJetUtils.cxx:20
JetClusterer::m_minrad
Gaudi::Property< float > m_minrad
Definition: JetClusterer.h:108
jet::ClusterSequence
fastjet::ClusterSequence ClusterSequence
Definition: ClusterSequence.h:21
endmsg
#define endmsg
Definition: AnalysisConfig_Ntuple.cxx:63
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
JetClustererHelper::seedsFromEventInfo
void seedsFromEventInfo(const xAOD::EventInfo *ei, std::vector< int > &seeds)
Fill seeds vector from run & event number. This functio is separated from the class so it's easier to...
Definition: JetClusterer.cxx:27
JetClusterer::buildClusterSequence
std::unique_ptr< fastjet::ClusterSequence > buildClusterSequence(const PseudoJetVector *pseudoJetvector) const
Used to create the cluster sequence.
Definition: JetClusterer.cxx:91
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
PseudoJetTranslator::translate
xAOD::Jet & translate(const fastjet::PseudoJet &pj, const PseudoJetContainer &pjCont, xAOD::JetContainer &jetCont, const xAOD::Vertex *originVertex=nullptr) const
Definition: PseudoJetTranslator.cxx:7
SG::VarHandleKey::initialize
StatusCode initialize(bool used=true)
If this object is used as a property, then this should be called during the initialize phase.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:103
xAOD::JetAlgorithmType::ID
ID
//////////////////////////////////////// JetAlgorithmType::ID defines most common physics jet finding...
Definition: JetContainerInfo.h:29
xAOD::JetAlgorithmType::undefined_jet_algorithm
@ undefined_jet_algorithm
Definition: JetContainerInfo.h:40
xAOD::JetInput::Type
Type
Definition: JetContainerInfo.h:54
DataVector
Derived DataVector<T>.
Definition: DataVector.h:581
SG::ReadHandle::isValid
virtual bool isValid() override final
Can the handle be successfully dereferenced?
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:192
ReadHandle.h
Handle class for reading from StoreGate.
JetClusterer.h
JetClusterer::m_jetRankAccessor
SG::AuxElement::Accessor< int > m_jetRankAccessor
Definition: JetClusterer.h:113
xAOD::JetAlgorithmType::cambridge_algorithm
@ cambridge_algorithm
Definition: JetContainerInfo.h:32
EventInfo.h
xAOD::JetAlgorithmType::antikt_algorithm
@ antikt_algorithm
Definition: JetContainerInfo.h:33
xAOD::EventInfo_v1
Class describing the basic event information.
Definition: EventInfo_v1.h:43
xAOD::Jet_v1
Class describing a jet.
Definition: Jet_v1.h:57
SG::WriteHandle
Definition: StoreGate/StoreGate/WriteHandle.h:76
PseudoJetVector
std::vector< fastjet::PseudoJet > PseudoJetVector
Definition: JetConstituentFiller.cxx:17
VertexContainer.h
DiTauMassTools::MaxHistStrategyV2::e
e
Definition: PhysicsAnalysis/TauID/DiTauMassTools/DiTauMassTools/HelperFunctions.h:26
xAOD::Vertex_v1
Class describing a Vertex.
Definition: Vertex_v1.h:42
SG::WriteHandle::record
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
JetContainer.h
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
JetClusterer::m_finalPseudoJets
SG::WriteHandleKey< PseudoJetVector > m_finalPseudoJets
used to build the key under which the final PJ will be stored in evtStore()
Definition: JetClusterer.h:90
AthCommonMsg< AlgTool >::msg
MsgStream & msg() const
Definition: AthCommonMsg.h:24
JetClusterer::getJets
std::pair< std::unique_ptr< xAOD::JetContainer >, std::unique_ptr< SG::IAuxStore > > getJets() const override
Return the final jets with their aux store.
Definition: JetClusterer.cxx:192
xAOD::JetAlgorithmType::algId
ID algId(const std::string &n)
Converts a string into a JetAlgorithmType::ID.
Definition: JetContainerInfo.cxx:76
JetAuxContainer.h
JetClusterer::m_ptmin
Gaudi::Property< float > m_ptmin
Definition: JetClusterer.h:97
PseudoJetContainer::casVectorPseudoJet
const std::vector< PseudoJet > * casVectorPseudoJet() const
Definition: PseudoJetContainer.cxx:135
defineDB.jets
list jets
Definition: JetTagCalibration/share/defineDB.py:24
python.Constants.VERBOSE
int VERBOSE
Definition: Control/AthenaCommon/python/Constants.py:14
FastJetUtils.h
JetClusterer::m_jetRank
Gaudi::Property< std::string > m_jetRank
Definition: JetClusterer.h:92
JetClusterer::m_useArea
bool m_useArea
Definition: JetClusterer.h:106
xAOD::EventInfo_v1::mcEventNumber
uint64_t mcEventNumber() const
The MC generator's event number.
xAOD::EventInfo_v1::eventType
bool eventType(EventType type) const
Check for one particular bitmask value.
JetClusterer::processPseudoJet
void processPseudoJet(const fastjet::PseudoJet &pj, const PseudoJetContainer &pjCont, xAOD::JetContainer *jets, const xAOD::Vertex *vertex) const
translate to xAOD::Jet
Definition: JetClusterer.cxx:151