ATLAS Offline Software
Loading...
Searching...
No Matches
TrackCaloClusterRecValidationTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
5//
6#include "GaudiKernel/SystemOfUnits.h"
9
14
16
17#include "TCCPlots.h"
18//
19#include <algorithm>
20#include <cmath> // to get std::isnan(), std::abs etc.
21#include <cstdlib> // to getenv
22#include <limits>
23#include <utility>
24#include <vector>
25
28 const std::string& name,
29 const IInterface* parent)
30 : ManagedMonitorToolBase(type, name, parent)
32{
33 declareProperty("JetCalibrationTools", m_jetCalibrationTools);
34 declareProperty("ApplyCalibration", m_applyCalibration = false);
35 declareProperty("CollectionsToCalibrate", m_jetCalibrationCollections);
36 declareProperty("SaveJetInfo", m_saveJetInfo = true);
37 declareProperty("JetTruthContainerName", m_truthJetContainerName);
38 declareProperty("JetTruthTrimmedContainerName", m_truthTrimmedJetContainerName);
39 declareProperty("JetContainerNames", m_jetContainerNames);
40 declareProperty("PrimaryVertexContainerName", m_vertexContainerName = "PrimaryVertices");
41 declareProperty("TopoJetReferenceName", m_topoJetReferenceName = "AntiKt10LCTopoJets");
42 declareProperty("TopoTrimmedJetReferenceName", m_topoTrimmedJetReferenceName = "AntiKt10LCTopoTrimmedJets");
43 declareProperty("maxTrkJetDR", m_maxJetDR = 0.75);
44 declareProperty("maxEta", m_maxEta = 2.0);
45 declareProperty("minPt", m_minPt = 200 * Gaudi::Units::GeV);
46 declareProperty("minMass", m_minMass = 50. * Gaudi::Units::GeV);
47 declareProperty("maxMass", m_maxMass = 150. * Gaudi::Units::GeV);
48 declareProperty("DirName", m_dirName = "TCCValidation/");
49 declareProperty("SubFolder", m_folder);
50 declareProperty("SaveTrackInfo", m_saveTrackInfo = false);
51 declareProperty("SaveMatchingInfo", m_saveMatchingInfo = false);
52 declareProperty("TrackCollectionName", m_trackParticleCollectionName = "InDetTrackParticles");
53 declareProperty("TrackPtMin", m_trackPtMin = 20. * Gaudi::Units::GeV);
54 declareProperty("JetPtBins", m_jetPtBins);
55 declareProperty("JetMassOverPtBins", m_jetMassOverPtBins);
56 declareProperty("TrackPtBins", m_trackPtBins);
57 declareProperty("TrackProdRadiusBins", m_trackProdRadiusBins);
58 declareProperty("SaveClusterInfo", m_saveClusterInfo = false);
59 declareProperty("ClusterCollectionName", m_caloClusterCollectionName = "TimedCaloCalTopoClusters");
60 declareProperty("ClusterEtaMax", m_caloClusterEtaMax = 2.5);
61 declareProperty("SaveTrackCaloClusterInfo", m_saveTCCInfo = false);
62 declareProperty("TCCCombinedCollectionNames", m_TCCCombinedCollectionNames);
63 declareProperty("TCCptMin", m_tccPtMin = 10. * Gaudi::Units::GeV);
64 declareProperty("TCCetaMax", m_tccEtaMax = 2.5);
65}
66
68
69StatusCode
71{
72 ATH_MSG_DEBUG("Initializing " << name() << "...");
74
75 // retrieve the jet calibration tool
78 ATH_MSG_WARNING("Number of collections to calibrate differs from the number of calibration tools... switching "
79 "off calibration!");
80 m_applyCalibration = false;
81 }
82 CHECK(m_jetCalibrationTools.retrieve());
83 }
84
85 if (m_saveJetInfo) {
86 for (const auto& name : m_jetContainerNames) {
87 ATH_MSG_INFO("Saving Plots for " << name << "...");
88 std::string myname = name;
89 if (name.find("AntiKt10LCTopo") != std::string::npos and name.find("My") == std::string::npos)
90 myname = "My" + name;
91
92 if (name == "AntiKt10TrackCaloClustersChargedJets")
93 myname = "AntiKt10TrackCaloClustersCombinedJets";
94 if (name == "AntiKt10TrackCaloClustersChargedTrimmedJets")
95 myname = "AntiKt10TrackCaloClustersCombinedTrimmedJets";
96
97 m_tccPlots.insert(std::pair<std::string, TCCPlots*>(name, new TCCPlots(nullptr, m_dirName + myname, "jets")));
98 m_tccPlots.at(name)->setJetPtBinning(m_jetPtBins);
99 m_tccPlots.at(name)->setJetMassOverPtBinning(m_jetMassOverPtBins);
100 }
101 }
102
103 if (m_saveTrackInfo) {
104 ATH_MSG_INFO("Saving Plots for " << m_trackParticleCollectionName << "...");
105 m_tccPlots.insert(std::pair<std::string, TCCPlots*>(
108 m_tccPlots.at(m_trackParticleCollectionName)->setTrackProdRadiusBinning(m_trackProdRadiusBins);
109 }
110
111 if (m_saveClusterInfo) {
112 ATH_MSG_INFO("Saving Plots for " << m_caloClusterCollectionName << "...");
113 m_tccPlots.insert(std::pair<std::string, TCCPlots*>(
115 }
116
117 if (m_saveTCCInfo) {
118 for (const auto& name : m_TCCCombinedCollectionNames) {
119 ATH_MSG_INFO("Saving Plots for " << name << "...");
120 m_tccPlots.insert(std::pair<std::string, TCCPlots*>(name, new TCCPlots(nullptr, m_dirName + name, "tccs")));
121 m_tccPlots.at(name)->setTrackPtBinning(m_trackPtBins);
122 }
123 }
124
125 ATH_CHECK(m_evt.initialize());
126
127 return StatusCode::SUCCESS;
128}
129
130StatusCode
132{
133
135 if (!evt.isValid()) {
136 ATH_MSG_FATAL("Unable to retrieve Event Info");
137 }
138 float mcEventWeight = evt->mcEventWeight();
139
140 if (m_saveJetInfo) {
141 ATH_MSG_DEBUG("Filling hists " << name() << "...");
142
144
145 // retrieve jet container
146 for (const auto& name : m_jetContainerNames) {
147
148 m_tccPlots.at(name)->setEventWeight(mcEventWeight);
149 ATH_MSG_DEBUG("Using Container " << name << "...");
150 ATH_MSG_DEBUG("-- weight = " << mcEventWeight << "...");
151
152 const auto *const jets_beforeCalib = getContainer<xAOD::JetContainer>(name);
153 if (not jets_beforeCalib) {
154 return StatusCode::FAILURE;
155 }
156
157 const xAOD::JetContainer* jets = jets_beforeCalib;
158
159 if (m_applyCalibration and
160 std::find(m_jetCalibrationCollections.begin(), m_jetCalibrationCollections.end(), name) !=
163 jets = calibrateAndRecordShallowCopyJetCollection(jets_beforeCalib, name);
164 if (!jets) {
165 ATH_MSG_WARNING("Unable to create calibrated jet shallow copy container");
166 return StatusCode::SUCCESS;
167 }
168 }
169
170 // Getting the collections for the pseudo response
171 const auto *const caloclusters = (name.find("Trimmed") == std::string::npos)
174 const auto *const truths = (name.find("Trimmed") == std::string::npos)
177
178 if (not truths) {
179 return StatusCode::FAILURE;
180 }
181
182 if (not caloclusters) {
183 return StatusCode::FAILURE;
184 }
185
186 m_tccPlots.at(name)->fill(*jets);
187
188 for (const auto jet : *jets) {
189 // conditions to be satisfied to select jets
190 if (fabs(jet->eta()) > m_maxEta)
191 continue;
192
193 // get the truth matched
194 const xAOD::Jet* truth_matched_nocuts = ClusterMatched(jet, truths);
195 // if truth_matched exists, fill the response w/o pt and mass cuts
196 if (truth_matched_nocuts)
197 m_tccPlots.at(name)->fillResponseNoPtNoMassCuts(*jet, *truth_matched_nocuts);
198
199 if (fabs(jet->pt()) < m_minPt)
200 continue;
201
202 // fill all jets histograms
203 m_tccPlots.at(name)->fill(*jet);
204 m_tccPlots.at(name)->fillMoments(*jet);
205
206 // fill all jets histograms + truth
207 for (const auto truth : *truths)
208 m_tccPlots.at(name)->fill(*jet, *truth);
209
210 // get the truth matched
211 const xAOD::Jet* truth_matched = ClusterMatched(jet, truths);
212
213 // apply mass requirement on the truth jet once you have matched
214 if (not truth_matched or (truth_matched->m() < m_minMass or truth_matched->m() > m_maxMass)) {
215 continue;
216 }
217
218 // if truth_matched exists, fill the jet histograms + truth matched
219 m_tccPlots.at(name)->fillResponse(*jet, *truth_matched);
220 m_tccPlots.at(name)->fillMomentsWithMassCut(*jet);
221
222 if (vertices) {
223 m_tccPlots.at(name)->fillResponseNPV(*jet, *truth_matched, vertices->size());
224 }
225
226 // get the calo matched
227 const xAOD::Jet* calo_matched = ClusterMatched(jet, caloclusters);
228 // if calo_matched exists, fill the jet histograms + calo matched
229 if (calo_matched) {
230 m_tccPlots.at(name)->fillPseudoResponse(*jet, *calo_matched);
231 }
232 }
233
234 ATH_MSG_DEBUG("All jets histograms filled! ...");
235
236 // evaluate the leadings in mass of the leadings is pt
237 std::vector<const xAOD::Jet*> leadings = { nullptr, nullptr };
238 std::vector<const xAOD::Jet*> leadings_nocuts = { nullptr, nullptr };
239
240 std::vector<const xAOD::Jet*> tmp_leadings;
241 if (!jets->empty()) {
242 tmp_leadings.push_back(jets->at(0));
243 }
244 if (jets->size() > 1) {
245 tmp_leadings.push_back(jets->at(1));
246 }
247
248 if (tmp_leadings.size() > 1 and tmp_leadings.at(0)->m() < tmp_leadings.at(1)->m()) {
249 std::swap(tmp_leadings.at(0), tmp_leadings.at(1));
250 }
251
252 // fill the leadings jets if they satisfy the eta requirement
253 if (!tmp_leadings.empty() and fabs(tmp_leadings.at(0)->eta()) < m_maxEta) {
254 leadings_nocuts.at(0) = tmp_leadings.at(0);
255 }
256
257 if (tmp_leadings.size() > 1 and fabs(tmp_leadings.at(1)->eta()) < m_maxEta) {
258 leadings_nocuts.at(1) = tmp_leadings.at(1);
259 }
260
261 std::vector<const xAOD::Jet*> truth_matches_nocuts = { nullptr, nullptr };
262 unsigned int pos = 0;
263 for (const auto& jet : leadings_nocuts) {
264 pos++;
265 if (not jet)
266 continue;
267 const xAOD::Jet* truth_matched_nocuts = ClusterMatched(jet, truths);
268 if (truth_matched_nocuts)
269 truth_matches_nocuts.at(pos - 1) = truth_matched_nocuts;
270 }
271
272 if (leadings_nocuts.at(0)) {
273 ATH_MSG_DEBUG(" ---> fillLeading w/o cuts ...");
274 if (truth_matches_nocuts.at(0))
275 m_tccPlots.at(name)->fillResponseNoPtNoMassCutsLeading(*leadings_nocuts.at(0), *truth_matches_nocuts.at(0));
276 ATH_MSG_DEBUG("Leading jet w/o cuts histograms filled! ...");
277 }
278
279 if (leadings_nocuts.at(1)) {
280 ATH_MSG_DEBUG(" ---> fillSubLeading w/o cuts ...");
281 if (truth_matches_nocuts.at(1))
282 m_tccPlots.at(name)->fillResponseNoPtNoMassCutsSubLeading(*leadings_nocuts.at(1),
283 *truth_matches_nocuts.at(1));
284 ATH_MSG_DEBUG("SubLeading jet w/o cuts histograms filled! ...");
285 }
286
287 // fill the leadings jets if they satisfy the eta and pt requirements
288 if (!tmp_leadings.empty() and fabs(tmp_leadings.at(0)->eta()) < m_maxEta and tmp_leadings.at(0)->pt() > m_minPt)
289 leadings.at(0) = tmp_leadings.at(0);
290
291 if (tmp_leadings.size() > 1 and fabs(tmp_leadings.at(1)->eta()) < m_maxEta and tmp_leadings.at(1)->pt() > m_minPt)
292 leadings.at(1) = tmp_leadings.at(1);
293
294 if (leadings.at(0)) {
295 m_tccPlots.at(name)->fillLeading(*leadings.at(0));
296 m_tccPlots.at(name)->fillMomentsLeading(*leadings.at(0));
297 }
298
299 if (leadings.at(1)) {
300 m_tccPlots.at(name)->fillSubLeading(*leadings.at(1));
301 m_tccPlots.at(name)->fillMomentsSubLeading(*leadings.at(1));
302 }
303
304 std::vector<const xAOD::Jet*> truth_matches = { nullptr, nullptr };
305 std::vector<const xAOD::Jet*> calo_matches = { nullptr, nullptr };
306 pos = 0;
307 for (const auto& jet : leadings) {
308 pos++;
309 if (not jet)
310 continue;
311 const xAOD::Jet* truth_matched = ClusterMatched(jet, truths);
312 if (truth_matched)
313 truth_matches.at(pos - 1) = truth_matched;
314 const xAOD::Jet* calo_matched = ClusterMatched(jet, caloclusters);
315 if (calo_matched)
316 calo_matches.at(pos - 1) = calo_matched;
317 }
318
319 if (leadings.at(0)) {
320 ATH_MSG_DEBUG(" ---> fillLeading ...");
321 if (truth_matches.at(0) and (truth_matches.at(0)->m() > m_minMass and truth_matches.at(0)->m() < m_maxMass)) {
322 m_tccPlots.at(name)->fillMomentsLeadingWithMassCut(*leadings.at(0));
323 m_tccPlots.at(name)->fillResponseLeading(*leadings.at(0), *truth_matches.at(0));
324 if (vertices)
325 m_tccPlots.at(name)->fillResponseLeadingNPV(*leadings.at(0), *truth_matches.at(0), vertices->size());
326 if (calo_matches.at(0))
327 m_tccPlots.at(name)->fillPseudoResponseLeading(*leadings.at(0), *calo_matches.at(0));
328 }
329 ATH_MSG_DEBUG("Leading jet histograms filled! ...");
330 }
331
332 if (leadings.at(1)) {
333 ATH_MSG_DEBUG(" ---> fillSubLeading ...");
334 if (truth_matches.at(1) and (truth_matches.at(1)->m() > m_minMass and truth_matches.at(1)->m() < m_maxMass)) {
335 m_tccPlots.at(name)->fillMomentsSubLeadingWithMassCut(*leadings.at(1));
336 m_tccPlots.at(name)->fillResponseSubLeading(*leadings.at(1), *truth_matches.at(1));
337 if (vertices)
338 m_tccPlots.at(name)->fillResponseSubLeadingNPV(*leadings.at(1), *truth_matches.at(1), vertices->size());
339 if (calo_matches.at(1))
340 m_tccPlots.at(name)->fillPseudoResponseSubLeading(*leadings.at(1), *calo_matches.at(1));
341 }
342 ATH_MSG_DEBUG("SubLeading jet histograms filled! ...");
343 }
344 }
345 }
346
347 // Getting the collections for TrackParticles
348 if (m_saveTrackInfo) {
350 if (not tracks)
351 return StatusCode::FAILURE;
352 for (const auto track : *tracks) {
354 m_tccPlots.at(m_trackParticleCollectionName)->fillMatching(*track);
355 m_tccPlots.at(m_trackParticleCollectionName)->fillTrackParametersAllPt(*track);
356 m_tccPlots.at(m_trackParticleCollectionName)->fillCaloEntryInfoAllPt(*track);
357 m_tccPlots.at(m_trackParticleCollectionName)->fillPerigeeInfoAllPt(*track);
358 m_tccPlots.at(m_trackParticleCollectionName)->fillPerigeeVsCaloEntryAllPt(*track);
359 if (track->pt() < m_trackPtMin)
360 continue;
361 m_tccPlots.at(m_trackParticleCollectionName)->fillTrackParameters(*track);
362 m_tccPlots.at(m_trackParticleCollectionName)->fillCaloEntryInfo(*track);
363 m_tccPlots.at(m_trackParticleCollectionName)->fillPerigeeInfo(*track);
364 m_tccPlots.at(m_trackParticleCollectionName)->fillPerigeeVsCaloEntry(*track);
365 }
366 }
367
368 // Getting the collections for the CaloClusters
369 if (m_saveClusterInfo) {
371 if (not clusters)
372 return StatusCode::FAILURE;
373 for (const auto cluster : *clusters) {
374 m_tccPlots.at(m_caloClusterCollectionName)->fillCluster(*cluster);
375 if (fabs(cluster->eta()) < m_caloClusterEtaMax)
376 m_tccPlots.at(m_caloClusterCollectionName)->fillClusterEtaCut(*cluster);
377 }
378 }
379
380 // Getting the collections for the TrackCaloClusters
381 if (m_saveTCCInfo) {
382 for (const auto& name : m_TCCCombinedCollectionNames) {
383 const auto *const tccs = getContainer<xAOD::TrackCaloClusterContainer>(name);
384 if (not tccs)
385 return StatusCode::FAILURE;
386 // fill the map with all the tracks creating tcc (means from PV0)
387 std::vector<const xAOD::TrackParticle*> allpv0tracks;
388 for (const auto tcc : *tccs) {
389 allpv0tracks.push_back(*tcc->trackParticleLink());
390 }
391
392 for (const auto tcc : *tccs) {
393 m_tccPlots.at(name)->fillTCC(*tcc, allpv0tracks);
394 if (tcc->pt() > m_tccPtMin)
395 m_tccPlots.at(name)->fillTCCptCut(*tcc);
396 if (fabs(tcc->eta()) < m_tccEtaMax)
397 m_tccPlots.at(name)->fillTCCetaCut(*tcc);
398 }
399 }
400 }
401
402 return StatusCode::SUCCESS;
403}
404
405const xAOD::Jet*
407{
408 std::vector<const xAOD::Jet*> myjets = {};
409 for (const auto tomatch : *jets)
410 myjets.push_back(tomatch);
411 return ClusterMatched(jet, myjets);
412}
413
414const xAOD::Jet*
415TrackCaloClusterRecValidationTool::ClusterMatched(const xAOD::Jet* jet, const std::vector<const xAOD::Jet*>& jets) const
416{
417 double minDeltaR = m_maxJetDR;
418 const xAOD::Jet* matched = nullptr;
419 for (const auto& tomatch : jets) {
420 if (jet->p4().DeltaR(tomatch->p4()) < minDeltaR) {
421 minDeltaR = jet->p4().DeltaR(tomatch->p4());
422 matched = tomatch;
423 }
424 }
425 return matched;
426}
427
428StatusCode
430{
431 ATH_MSG_INFO("Booking hists " << name() << "...");
432 for (auto& plots : m_tccPlots) {
433 plots.second->setDetailLevel(100); // DEBUG, enable expert histograms
434 plots.second->initialize();
435 std::vector<HistData> hists = plots.second->retrieveBookedHistograms();
436 for (const auto& hist : hists) {
437 ATH_CHECK(regHist(hist.first, hist.second, all));
438 }
439 }
440
441 return StatusCode::SUCCESS;
442}
443
444StatusCode
446{
447 ATH_MSG_INFO("Finalising hists " << name() << "...");
448
449 if (endOfRunFlag()) {
450 for (auto& plots : m_tccPlots)
451 plots.second->finalize();
452 }
453
454 ATH_MSG_INFO("Successfully finalized hists");
455 return StatusCode::SUCCESS;
456}
457
461 const std::string& name)
462{
463
464 // create a shallow copy of the jet container
465 std::pair<xAOD::JetContainer*, xAOD::ShallowAuxContainer*> shallowCopy = xAOD::shallowCopyContainer(*jetContainer);
466 xAOD::JetContainer* jetContainerShallowCopy = shallowCopy.first;
467 xAOD::ShallowAuxContainer* jetAuxContainerShallowCopy = shallowCopy.second;
468
469 if (evtStore()->record(jetContainerShallowCopy, name + "_Calib").isFailure()) {
470 ATH_MSG_WARNING("Unable to record JetCalibratedContainer: " << name + "_Calib");
471 return nullptr;
472 }
473 if (evtStore()->record(jetAuxContainerShallowCopy, name + "_Calib" + "Aux.").isFailure()) {
474 ATH_MSG_WARNING("Unable to record JetCalibratedAuxContainer: " << name + "_Calib" + "Aux.");
475 return nullptr;
476 }
477
478 static const SG::AuxElement::Accessor<xAOD::IParticleLink> accSetOriginLink("originalObjectLink");
479 static const SG::AuxElement::Decorator<float> decJvt("JvtUpdate");
480
481 int pos = std::find(m_jetCalibrationCollections.begin(), m_jetCalibrationCollections.end(), name) -
483 if (m_jetCalibrationTools[pos]->applyCalibration(*jetContainerShallowCopy).isFailure()) {
484 ATH_MSG_WARNING("Failed to apply calibration to the jet container");
485 return nullptr;
486 }
487
488 for (xAOD::Jet* shallowCopyJet : *jetContainerShallowCopy) {
489 const xAOD::IParticleLink originLink(*jetContainer, shallowCopyJet->index());
490 accSetOriginLink(*shallowCopyJet) = originLink;
491 }
492
493 if (evtStore()->setConst(jetContainerShallowCopy).isFailure()) {
494 ATH_MSG_WARNING("Failed to set jetcalibCollection (" << name + "_Calib" + "Aux."
495 << ")const in StoreGate!");
496 return nullptr;
497 }
498 if (evtStore()->setConst(jetAuxContainerShallowCopy).isFailure()) {
499 ATH_MSG_WARNING("Failed to set jetcalibCollection (" << name + "_Calib" + "Aux."
500 << ")const in StoreGate!");
501 return nullptr;
502 }
503
504 return jetContainerShallowCopy;
505}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
#define CHECK(...)
Evaluate an expression and check for errors.
header file for class of same name
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
ServiceHandle< StoreGateSvc > & evtStore()
virtual StatusCode regHist(TH1 *h, const std::string &system, Interval_t interval, MgmtAttr_t histo_mgmt=ATTRIB_MANAGED, const std::string &chain="", const std::string &merge="")
Registers a TH1 (including TH2, TH3, and TProfile) to be included in the output stream using logical ...
ManagedMonitorToolBase(const std::string &type, const std::string &name, const IInterface *parent)
SG::Decorator< T, ALLOC > Decorator
Definition AuxElement.h:575
SG::Accessor< T, ALLOC > Accessor
Definition AuxElement.h:572
ToolHandleArray< IJetCalibrationTool > m_jetCalibrationTools
calibration tool
virtual ~TrackCaloClusterRecValidationTool()
Destructor.
virtual StatusCode procHistograms()
An inheriting class should either override this function or finalHists().
virtual StatusCode fillHistograms()
An inheriting class should either override this function or fillHists().
virtual StatusCode bookHistograms()
An inheriting class should either override this function or bookHists().
TrackCaloClusterRecValidationTool()
prevent default construction
const xAOD::Jet * ClusterMatched(const xAOD::Jet *jet, const xAOD::JetContainer *jets)
Get the matched jet.
const T * getContainer(const std::string &containerName)
SG::ReadHandleKey< xAOD::EventInfo > m_evt
const xAOD::JetContainer * calibrateAndRecordShallowCopyJetCollection(const xAOD::JetContainer *jetContainer, const std::string &name)
Calibrate and record a shallow copy of a given jet container.
std::map< std::string, TCCPlots * > m_tccPlots
std::string m_truthJetContainerName
Truth jet container's name.
virtual double m() const
The invariant mass of the particle.
Definition Jet_v1.cxx:59
Class creating a shallow copy of an existing auxiliary container.
void swap(ElementLinkVector< DOBJ > &lhs, ElementLinkVector< DOBJ > &rhs)
Jet_v1 Jet
Definition of the current "jet version".
std::pair< std::unique_ptr< T >, std::unique_ptr< ShallowAuxContainer > > shallowCopyContainer(const T &cont, const EventContext &ctx)
Function making a shallow copy of a constant container.
IParticleLink_v1 IParticleLink
Define the latest version of the IParticleLink class.
JetContainer_v1 JetContainer
Definition of the current "jet container version".