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