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
86 if (m_saveJetInfo) {
87 for (const auto& name : m_jetContainerNames) {
88 ATH_MSG_INFO("Saving Plots for " << name << "...");
89 std::string myname = name;
90 if (name.find("AntiKt10LCTopo") != std::string::npos and name.find("My") == std::string::npos)
91 myname = "My" + name;
92
93 if (name == "AntiKt10TrackCaloClustersChargedJets")
94 myname = "AntiKt10TrackCaloClustersCombinedJets";
95 if (name == "AntiKt10TrackCaloClustersChargedTrimmedJets")
96 myname = "AntiKt10TrackCaloClustersCombinedTrimmedJets";
97
98 m_tccPlots.insert(std::pair<std::string, TCCPlots*>(name, new TCCPlots(nullptr, m_dirName + myname, "jets")));
99 m_tccPlots.at(name)->setJetPtBinning(m_jetPtBins);
100 m_tccPlots.at(name)->setJetMassOverPtBinning(m_jetMassOverPtBins);
101 }
102 }
103
104 if (m_saveTrackInfo) {
105 ATH_MSG_INFO("Saving Plots for " << m_trackParticleCollectionName << "...");
106 m_tccPlots.insert(std::pair<std::string, TCCPlots*>(
109 m_tccPlots.at(m_trackParticleCollectionName)->setTrackProdRadiusBinning(m_trackProdRadiusBins);
110 }
111
112 if (m_saveClusterInfo) {
113 ATH_MSG_INFO("Saving Plots for " << m_caloClusterCollectionName << "...");
114 m_tccPlots.insert(std::pair<std::string, TCCPlots*>(
116 }
117
118 if (m_saveTCCInfo) {
119 for (const auto& name : m_TCCCombinedCollectionNames) {
120 ATH_MSG_INFO("Saving Plots for " << name << "...");
121 m_tccPlots.insert(std::pair<std::string, TCCPlots*>(name, new TCCPlots(nullptr, m_dirName + name, "tccs")));
122 m_tccPlots.at(name)->setTrackPtBinning(m_trackPtBins);
123 }
124 }
125
126 ATH_CHECK(m_evt.initialize());
127
128 return StatusCode::SUCCESS;
129}
130
131StatusCode
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, ctx);
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 const EventContext& ctx)
463{
464
465 // create a shallow copy of the jet container
467 xAOD::shallowCopy(*jetContainer, ctx);
468
469 int pos = std::find(m_jetCalibrationCollections.begin(), m_jetCalibrationCollections.end(), name) -
471 if (m_jetCalibrationTools[pos]->applyCalibration(*shallowCopy.first).isFailure()) {
472 ATH_MSG_WARNING("Failed to apply calibration to the jet container");
473 return nullptr;
474 }
475
476 static const SG::AuxElement::Accessor<xAOD::IParticleLink> accSetOriginLink("originalObjectLink");
477 for (xAOD::Jet* shallowCopyJet : *shallowCopy.first) {
478 const xAOD::IParticleLink originLink(*jetContainer, shallowCopyJet->index());
479 accSetOriginLink(*shallowCopyJet) = originLink;
480 }
481
482 xAOD::JetContainer* jetContainerShallowCopy = shallowCopy.first.get();
483
484 if (evtStore()->record(std::move(shallowCopy.first), name + "_Calib").isFailure()) {
485 ATH_MSG_WARNING("Unable to record JetCalibratedContainer: " << name + "_Calib");
486 return nullptr;
487 }
488 if (evtStore()->record(std::move(shallowCopy.second), name + "_Calib" + "Aux.").isFailure()) {
489 ATH_MSG_WARNING("Unable to record JetCalibratedAuxContainer: " << name + "_Calib" + "Aux.");
490 return nullptr;
491 }
492
493 return jetContainerShallowCopy;
494}
#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)
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".