ATLAS Offline Software
JetCaloQualityToolFE.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 
8 
10 #include "xAODPFlow/FlowElement.h"
11 #include "PFlowUtils/FEHelpers.h"
12 
13 #include <iostream>
14 #include <iomanip>
15 using namespace std;
16 
18  : asg::AsgTool(name)
19 {
20 }
21 
23  ATH_MSG_DEBUG( "Inside initialize() method" );
24 
25  if(!m_writeDecorKeys.empty()){
26  ATH_MSG_ERROR("OutputDecorKeys should not be configured manually!");
27  return StatusCode::FAILURE;
28  }
29  if(m_jetContainerName.empty()){
30  ATH_MSG_ERROR("JetCaloQualityToolFE needs to have its input jet container name configured!");
31  return StatusCode::FAILURE;
32  }
33 
34  // Set the DecorHandleKeys with the correct strings
35  for( const std::string & calcN : m_calculationNames){
36 
37  if(calcN == "LArQuality"){
38  m_doLArQ = true;
39  }
40  else if(calcN == "HECQuality"){
41  m_doHECQ = true;
42  }
43  else if(calcN == "NegativeE"){
44  m_doNegE = true;
45  }
46  else if(calcN == "AverageLArQF"){
47  m_doAvgLAr = true;
48  }
49  else if(calcN == "Timing"){
50  m_doTime = true;
51  }
52  else if(calcN == "Centroid"){
53  m_doCentroid = true;
54  }
55  else if(calcN == "BchCorrCell"){
56  m_doBchCorrCell = true;
57  }
58 
59  if(calcN == "Centroid"){
60  m_writeDecorKeys.emplace_back(m_jetContainerName + "." + calcN+"R");
61  }
62  else{
63  m_writeDecorKeys.emplace_back(m_jetContainerName + "." + calcN);
64  }
65  }
66 
67  // Define OOT calculators.
68  for( const double timeCut : m_timingTimeCuts){
69  // build the moment name from the base-name and the value of the timing cut
70  std::stringstream s;
71  s << std::setprecision(0) << std::fixed << "OotFracClusters" << timeCut;
72  m_writeDecorKeys_OOT.emplace_back(m_jetContainerName + "." + s.str());
73  }
74 
75  // Define tresholds for NXConstituents:
76  for( const int fracCut: m_thresholdCuts){
77  std::ostringstream sout;
78  sout << "N" << fracCut << "Constituents";
79  m_writeDecorKeys_Nfrac.emplace_back(m_jetContainerName + "." + sout.str());
80  }
81 
82  ATH_CHECK(m_writeDecorKeys.initialize());
83  if(!m_writeDecorKeys_OOT.empty()){
84  ATH_CHECK(m_writeDecorKeys_OOT.initialize());
85  }
86  if(!m_writeDecorKeys_Nfrac.empty()){
87  ATH_CHECK(m_writeDecorKeys_Nfrac.initialize());
88  }
89 
90  return StatusCode::SUCCESS;
91 }
92 
94 {
95 
96  ATH_MSG_VERBOSE("Begin decorating jets.");
97 
98  for(const xAOD::Jet* jet : jets) {
100  }
101 
102  return StatusCode::SUCCESS;
103 }
104 
105 std::vector<const xAOD::CaloCluster*> JetCaloQualityToolFE::extractConstituents(const xAOD::Jet& jet) const{
106 
107  std::vector<const xAOD::CaloCluster*> clusters;
108 
109  // Get the input type:
110  xAOD::Type::ObjectType ctype = jet.rawConstituent(0)->type();
111 
112  if ( ctype == xAOD::Type::CaloCluster ) {
113  ATH_MSG_VERBOSE(" Constituents are calo clusters.");
114  for ( size_t i = 0; i < jet.numConstituents(); i++ ) {
115  const xAOD::CaloCluster* constit = static_cast<const xAOD::CaloCluster*>(jet.rawConstituent(i));
116  clusters.push_back(constit);
117  }
118  }
119  else if( ctype == xAOD::Type::FlowElement ){
120 
121  ATH_MSG_VERBOSE(" Constituents are FlowElements.");
122 
123  //Need to distinguish between ParticleFlow and UFOs
124  const xAOD::FlowElement* constit0 = static_cast<const xAOD::FlowElement*>(jet.rawConstituent(0));
125 
126  // If jet constituents are ParticleFlow objects (stored as FlowElements)
127  if(constit0->signalType() & xAOD::FlowElement::PFlow){
128  ATH_MSG_VERBOSE(" Constituents are ParticleFlow objects stored as FlowElements.");
129  for ( size_t i = 0; i < jet.numConstituents(); i++ ) {
130  const xAOD::FlowElement* constit = static_cast<const xAOD::FlowElement*>(jet.rawConstituent(i));
131  // Use only neutral PFOs
132  if(constit->isCharged())
133  continue;
134 
135  if(constit->nOtherObjects() >= 1){
136  const xAOD::CaloCluster* cluster = dynamic_cast<const xAOD::CaloCluster*>(constit->otherObject(0));
137  if(cluster != nullptr){
138  clusters.push_back(cluster);
139  }
140  }
141  }
142  }
143  else{ // jet constituents are UFOs (stored as FlowElements)
144  ATH_MSG_VERBOSE(" Constituents are UFOs stored as FlowElements.");
145 
146  for ( size_t i = 0; i < jet.numConstituents(); i++ ) {
147  const xAOD::FlowElement* constit = static_cast<const xAOD::FlowElement*>(jet.rawConstituent(i));
148 
149  //Reject charged UFOs (but keep combined UFOs)
151  continue;
152 
153  // For UFOs, otherObjects are links to the underlying ParticleFlow objects
154  for (size_t n = 0; n < constit->otherObjects().size(); ++n) {
155  if(! constit->otherObject(n)) continue;
156  int index_pfo = constit->otherObject(n)->index();
157  if(index_pfo<0) continue;
158 
159  const auto* fe = (constit->otherObject(n));
160  const xAOD::CaloCluster* cluster = nullptr;
161 
162  if(fe->type() == xAOD::Type::FlowElement){
163  const xAOD::FlowElement* pfo = dynamic_cast<const xAOD::FlowElement*>(fe);
164  if(!pfo->otherObjects().empty() && pfo->otherObject(0) && pfo->otherObject(0)->type() == xAOD::Type::CaloCluster){
165  cluster = dynamic_cast<const xAOD::CaloCluster*> (pfo->otherObject(0));
166  }
167  }
168  if(!cluster){continue;}
169 
170  if(std::find(clusters.begin(), clusters.end(), cluster) == clusters.end()){
171  clusters.push_back(cluster);
172  }
173  }
174  }
175  }
176  }
177 
178  return clusters;
179 
180 }
181 
183 
184  // First, extract the constituents directly (in case of cluster-based jet) or underlying clusters
185  std::vector<const xAOD::CaloCluster*> clusters = extractConstituents(jet);
186 
187  // Calculate moments
188  float sum_E = 0.0;
189  float sum_E_square = 0.0;
190 
191  float sum_badLarQ = 0.0;
192  float sum_badHECQ = 0.0;
193  float sum_e_HEC = 0.0;
194  float sum_e_neg = 0.0;
195  float sum_avg_lar_q = 0.0;
196  float sum_timing = 0.0;
197  float centroid_x = 0.0, centroid_y = 0.0, centroid_z = 0.0;
198  float sum_e_bad_cells = 0.0;
199 
200  std::vector<float> sum_OOT;
201  sum_OOT.resize(m_timingTimeCuts.size());
202 
203  std::vector<int> counter_Nfrac;
204  counter_Nfrac.resize(m_thresholdCuts.size());
205 
206  std::vector<float> cluster_energies;
207 
208  for ( size_t i = 0; i < clusters.size(); i++){
209 
210  const xAOD::CaloCluster* constit = static_cast<const xAOD::CaloCluster*>(clusters[i]);
211 
212  float cluster_E = constit->e(xAOD::CaloCluster::UNCALIBRATED);
213 
214  sum_E += cluster_E;
215  sum_E_square += cluster_E*cluster_E;
216 
217  cluster_energies.push_back(cluster_E);
218 
219  //LArQuality || HECQuality
220  double bad_frac=0.0;
221  if(m_doLArQ || m_doHECQ){
223 
224  if(m_doLArQ){
225  sum_badLarQ += bad_frac*cluster_E;
226  }
227 
228  if(m_doHECQ){
229  float e_HEC = constit->eSample( CaloSampling::HEC0) + constit->eSample( CaloSampling::HEC1) + constit->eSample( CaloSampling::HEC2) + constit->eSample( CaloSampling::HEC3);
230  sum_e_HEC += e_HEC;
231  sum_badHECQ += bad_frac*e_HEC;
232  }
233  }
234 
235  //NegativeE
236  if(m_doNegE){
237  double e_pos=0.0;
239  sum_e_neg += cluster_E - e_pos;
240  }
241 
242  //JetCalcAverageLArQualityF
243  if(m_doAvgLAr){
244  double avg_lar_q=0.0;
245  constit->retrieveMoment(xAOD::CaloCluster::AVG_LAR_Q, avg_lar_q);
246  sum_avg_lar_q += avg_lar_q*cluster_E*cluster_E;
247  }
248 
249  //Centroid
250  if(m_doCentroid){
251  double x = 0.0, y = 0.0, z = 0.0;
255 
256  centroid_x += x*cluster_E;
257  centroid_y += y*cluster_E;
258  centroid_z += z*cluster_E;
259  }
260 
261  //BchCorrCell
262  if(m_doBchCorrCell){
263  double cells_bad_E = 0.0;
264  constit->retrieveMoment(xAOD::CaloCluster::ENG_BAD_CELLS, cells_bad_E);
265  sum_e_bad_cells += cells_bad_E;
266  }
267 
268  //Timing / OOT
269  if(m_doTime || m_timingTimeCuts.size() > 0){
270  double timing = constit->time();
271 
272  if(m_doTime){
273  sum_timing += timing*cluster_E*cluster_E;
274  }
275 
276  //OOT
277  for(size_t j = 0; j < m_timingTimeCuts.size(); j++){
278  if(std::abs(timing) > m_timingTimeCuts[j]){
279  sum_OOT[j] += cluster_E;
280  }
281  }
282  }
283  } // end loop over all all constituents
284 
285 
286  if(m_thresholdCuts.size() > 0){
287 
288  std::sort(cluster_energies.rbegin(),cluster_energies.rend());
289 
290  for(size_t iFracCut = 0; iFracCut < m_thresholdCuts.size(); iFracCut++){
291 
292  int counter = 0;
293  float tmp_sum = 0;
294 
295  for(unsigned int iClus = 0; iClus < cluster_energies.size(); iClus++){
296  tmp_sum += cluster_energies[iClus];
297  counter++;
298  if(tmp_sum > m_thresholdCuts[iFracCut]*sum_E/100.) break;
299  }
300  counter_Nfrac[iFracCut] = counter;
301  }
302  }
303 
304  //Add the decorations
305  for(size_t i = 0; i < m_calculationNames.size(); i++){
306  std::string calcN = m_calculationNames[i];
307 
309 
310  if(calcN == "LArQuality"){
311  decHandle(jet) = sum_E != 0. ? sum_badLarQ/sum_E : 0.;
312  }
313  else if(calcN == "HECQuality"){
314  decHandle(jet) = sum_e_HEC != 0. ? sum_badHECQ/sum_e_HEC : 0.;
315  }
316  else if(calcN == "NegativeE"){
317  decHandle(jet) = sum_e_neg;
318  }
319  else if(calcN == "AverageLArQF"){
320  decHandle(jet) = sum_E_square != 0. ? sum_avg_lar_q/sum_E_square : 0.;
321  }
322  else if(calcN == "Timing"){
323  decHandle(jet) = sum_E_square != 0. ? sum_timing/sum_E_square : 0.;
324  }
325  else if(calcN == "Centroid"){
326  decHandle(jet) = sum_E_square != 0. ? sqrt(centroid_x*centroid_x+centroid_y*centroid_y+centroid_z*centroid_z)/sum_E_square : 0.;
327  }
328  else if(calcN == "BchCorrCell"){
329  decHandle(jet) = jet.jetP4(xAOD::JetEMScaleMomentum).E() != 0. ? sum_e_bad_cells/jet.jetP4(xAOD::JetEMScaleMomentum).E() : 0. ;
330  }
331  }
332 
333  for( size_t iCut = 0; iCut < m_timingTimeCuts.size(); iCut++){
335  decHandle_timing(jet) = sum_E != 0. ? sum_OOT[iCut]/sum_E : 0. ;
336  }
337 
338  for( size_t iFracCut = 0; iFracCut < m_thresholdCuts.size(); iFracCut++){
339  //Variable was previously stored as float rather than int
340  //Keep float to not break e.g. jet calibration with derivations storing variable as float
342  decHandle_frac(jet) = counter_Nfrac[iFracCut];
343  }
344 }
JetCaloQualityToolFE::m_doNegE
bool m_doNegE
Definition: JetCaloQualityToolFE.h:58
xAOD::CaloCluster_v1::time
flt_t time() const
Access cluster time.
FEHelpers.h
python.SystemOfUnits.s
int s
Definition: SystemOfUnits.py:131
JetCaloQualityToolFE::m_doLArQ
bool m_doLArQ
Definition: JetCaloQualityToolFE.h:56
JetCaloQualityToolFE::m_calculationNames
Gaudi::Property< std::vector< std::string > > m_calculationNames
Definition: JetCaloQualityToolFE.h:34
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
JetCaloQualityToolFE::fillQualityVariables
void fillQualityVariables(const xAOD::Jet &jet) const
Definition: JetCaloQualityToolFE.cxx:182
xAOD::CaloCluster_v1::CENTER_X
@ CENTER_X
Cluster Centroid ( )
Definition: CaloCluster_v1.h:131
ObjectType
ObjectType
Definition: BaseObject.h:11
xAOD::FlowElement_v1::nOtherObjects
std::size_t nOtherObjects() const
Definition: FlowElement_v1.cxx:192
JetCaloQualityToolFE::m_writeDecorKeys
SG::WriteDecorHandleKeyArray< xAOD::JetContainer > m_writeDecorKeys
Definition: JetCaloQualityToolFE.h:43
xAOD::CaloCluster_v1::AVG_LAR_Q
@ AVG_LAR_Q
Sum(E_cell_LAr^2 Q_cell_LAr)/Sum(E_cell_LAr^2)
Definition: CaloCluster_v1.h:163
JetCaloQualityToolFE::m_thresholdCuts
Gaudi::Property< std::vector< int > > m_thresholdCuts
Definition: JetCaloQualityToolFE.h:38
asg
Definition: DataHandleTestTool.h:28
JetCaloQualityToolFE::m_doBchCorrCell
bool m_doBchCorrCell
Definition: JetCaloQualityToolFE.h:61
JetCaloQualityToolFE::m_timingTimeCuts
Gaudi::Property< std::vector< double > > m_timingTimeCuts
Definition: JetCaloQualityToolFE.h:36
JetCaloQualityToolFE.h
xAOD::IParticle::type
virtual Type::ObjectType type() const =0
The type of the object as a simple enumeration.
CaloCell_ID_FCS::HEC2
@ HEC2
Definition: FastCaloSim_CaloCell_ID.h:29
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
x
#define x
JetAccessorMap.h
xAOD::CaloCluster
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
Definition: Event/xAOD/xAODCaloEvent/xAODCaloEvent/CaloCluster.h:19
PUClassification.Charged
Charged
Definition: PUClassification.py:16
JetCaloQualityToolFE::decorate
virtual StatusCode decorate(const xAOD::JetContainer &jets) const override
Decorate a jet collection without otherwise modifying it.
Definition: JetCaloQualityToolFE.cxx:93
xAOD::FlowElement_v1::PFlow
@ PFlow
Definition: FlowElement_v1.h:45
xAOD::CaloCluster_v1::CENTER_Z
@ CENTER_Z
Cluster Centroid ( )
Definition: CaloCluster_v1.h:133
xAOD::FlowElement_v1::isCharged
bool isCharged() const
Definition: FlowElement_v1.cxx:56
JetCaloQualityToolFE::m_writeDecorKeys_Nfrac
SG::WriteDecorHandleKeyArray< xAOD::JetContainer > m_writeDecorKeys_Nfrac
Definition: JetCaloQualityToolFE.h:49
xAOD::CaloCluster_v1
Description of a calorimeter cluster.
Definition: CaloCluster_v1.h:59
JetCaloQualityToolFE::JetCaloQualityToolFE
JetCaloQualityToolFE(const std::string &name)
Definition: JetCaloQualityToolFE.cxx:17
jet
Definition: JetCalibTools_PlotJESFactors.cxx:23
CaloCell_ID_FCS::HEC1
@ HEC1
Definition: FastCaloSim_CaloCell_ID.h:28
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
trigDumpTimers.timing
def timing(hist)
Definition: trigDumpTimers.py:13
FlowElement.h
lumiFormat.i
int i
Definition: lumiFormat.py:92
CaloCluster.h
z
#define z
beamspotman.n
n
Definition: beamspotman.py:731
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
xAOD::FlowElement
FlowElement_v1 FlowElement
Definition of the current "pfo version".
Definition: FlowElement.h:16
SG::WriteDecorHandle
Handle class for adding a decoration to an object.
Definition: StoreGate/StoreGate/WriteDecorHandle.h:99
JetCaloQualityToolFE::m_doAvgLAr
bool m_doAvgLAr
Definition: JetCaloQualityToolFE.h:59
xAOD::FlowElement_v1::signalType
signal_t signalType() const
JetCaloQualityToolFE::m_doCentroid
bool m_doCentroid
Definition: JetCaloQualityToolFE.h:60
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
xAOD::CaloCluster_v1::retrieveMoment
bool retrieveMoment(MomentType type, double &value) const
Retrieve individual moment.
Definition: CaloCluster_v1.cxx:738
JetCaloQualityToolFE::m_writeDecorKeys_OOT
SG::WriteDecorHandleKeyArray< xAOD::JetContainer > m_writeDecorKeys_OOT
Definition: JetCaloQualityToolFE.h:46
SG::AuxElement::index
size_t index() const
Return the index of this element within its container.
DataVector
Derived DataVector<T>.
Definition: DataVector.h:581
WriteDecorHandle.h
Handle class for adding a decoration to an object.
xAOD::CaloCluster_v1::ENG_BAD_CELLS
@ ENG_BAD_CELLS
Total em-scale energy of bad cells in this cluster.
Definition: CaloCluster_v1.h:148
JetCaloQualityToolFE::extractConstituents
std::vector< const xAOD::CaloCluster * > extractConstituents(const xAOD::Jet &jet) const
Definition: JetCaloQualityToolFE.cxx:105
xAOD::JetEMScaleMomentum
@ JetEMScaleMomentum
Definition: JetTypes.h:28
xAOD::CaloCluster_v1::UNCALIBRATED
@ UNCALIBRATED
Definition: CaloCluster_v1.h:306
JetCaloQualityToolFE::m_doTime
bool m_doTime
Definition: JetCaloQualityToolFE.h:62
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:192
JetCaloQualityToolFE::m_doHECQ
bool m_doHECQ
Definition: JetCaloQualityToolFE.h:57
CaloCell_ID_FCS::HEC0
@ HEC0
Definition: FastCaloSim_CaloCell_ID.h:27
xAOD::Jet_v1
Class describing a jet.
Definition: Jet_v1.h:57
xAOD::CaloCluster_v1::eSample
float eSample(const CaloSample sampling) const
Definition: CaloCluster_v1.cxx:521
y
#define y
std::sort
void sort(typename std::reverse_iterator< DataModel_detail::iterator< DVL > > beg, typename std::reverse_iterator< DataModel_detail::iterator< DVL > > end, const Compare &comp)
Specialization of sort for DataVector/List.
Definition: DVL_algorithms.h:623
xAOD::FlowElement_v1::otherObject
const xAOD::IParticle * otherObject(std::size_t i) const
Definition: FlowElement_v1.cxx:196
RunTileMonitoring.clusters
clusters
Definition: RunTileMonitoring.py:133
defineDB.jets
list jets
Definition: JetTagCalibration/share/defineDB.py:24
CaloCell_ID_FCS::HEC3
@ HEC3
Definition: FastCaloSim_CaloCell_ID.h:30
test_pyathena.counter
counter
Definition: test_pyathena.py:15
JetCaloQualityToolFE::initialize
virtual StatusCode initialize() override
Dummy implementation of the initialisation function.
Definition: JetCaloQualityToolFE.cxx:22
xAOD::CaloCluster_v1::e
virtual double e() const
The total energy of the particle.
Definition: CaloCluster_v1.cxx:265
xAOD::CaloCluster_v1::CENTER_Y
@ CENTER_Y
Cluster Centroid ( )
Definition: CaloCluster_v1.h:132
xAOD::CaloCluster_v1::ENG_POS
@ ENG_POS
Total positive Energy of this cluster.
Definition: CaloCluster_v1.h:156
xAOD::FlowElement_v1::otherObjects
std::vector< const xAOD::IParticle * > otherObjects() const
Definition: FlowElement_v1.cxx:163
JetCaloQualityToolFE::m_jetContainerName
Gaudi::Property< std::string > m_jetContainerName
Definition: JetCaloQualityToolFE.h:40
xAOD::FlowElement_v1
A detector object made of other lower level object(s)
Definition: FlowElement_v1.h:25
xAOD::CaloCluster_v1::BADLARQ_FRAC
@ BADLARQ_FRAC
Energy fraction of LAr cells with quality larger than a given cut.
Definition: CaloCluster_v1.h:155