ATLAS Offline Software
GetLCOutOfCluster.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 //-----------------------------------------------------------------------
6 // File and Version Information:
7 // $Id: GetLCOutOfCluster.cxx,v 1.2 2008-11-04 14:33:37 menke Exp $
8 //
9 // Description: see GetLCOutOfCluster.h
10 //
11 // Environment:
12 // Software developed for the ATLAS Detector at CERN LHC
13 //
14 // Author List:
15 // Sven Menke
16 //
17 //-----------------------------------------------------------------------
18 
19 //-----------------------
20 // This Class's Header --
21 //-----------------------
23 
24 //---------------
25 // C++ Headers --
26 //---------------
30 #include "StoreGate/ReadHandle.h"
31 
33 
34 #include "TFile.h"
35 #include "TProfile2D.h"
36 #include "TString.h"
37 #include <iterator>
38 #include <cmath>
39 
40 //###############################################################################
42  ISvcLocator* pSvcLocator)
43  : AthAlgorithm(name, pSvcLocator),
44  m_outputFile(nullptr),
45  m_clusterCollName("CaloTopoClusters"),
46  m_NormalizationType("Lin"),
47  m_NormalizationTypeNumber(0),
48  m_ClassificationType("None"),
49  m_ClassificationTypeNumber(0)
50 {
51 
52  std::vector<Gaudi::Histo1DDef> dims(6);
53  dims[0] = Gaudi::Histo1DDef("side",-1.5,1.5,1);
54  dims[1] = Gaudi::Histo1DDef("|eta|",0.,5.,50);
55  dims[2] = Gaudi::Histo1DDef("phi",-M_PI,M_PI,1);
56  dims[3] = Gaudi::Histo1DDef("log10(E_clus (MeV))",log10(200),log10(1e6),14);
57  dims[4] = Gaudi::Histo1DDef("log10(lambda_clus (mm))",0.0,4.0,14);
58  dims[5] = Gaudi::Histo1DDef("weight",0.,3.0,1);
59 
60  mapinsert(dims);
61 
62  // Dimensions to use for classification
63  declareProperty("OutOfClusterDimensions",m_dimensionsmap);
64 
65  // Name of output file to save histograms in
66  declareProperty("OutputFileName",m_outputFileName);
67 
68  // Name of ClusterContainer to use
69  declareProperty("ClusterCollectionName",m_clusterCollName);
70 
71  // Name of Samplings to ignore
72  m_invalidSamplingNames.resize(3);
73 
74  m_invalidSamplingNames[0] = "PreSamplerB";
75  m_invalidSamplingNames[1] = "PreSamplerE";
76  m_invalidSamplingNames[2] = "TileGap3";
77 
78  declareProperty("InvalidSamplings",m_invalidSamplingNames);
79 
80  // Normalization type "Const", "Lin", "Log", "NClus"
81  declareProperty("NormalizationType",m_NormalizationType);
82 
83  // Classification type "None" for single pion MC or
84  // "ParticleID_EM" for ParticleID based em-type clusters
85  // "ParticleID_HAD" for ParticleID based had-type clusters
86  declareProperty("ClassificationType", m_ClassificationType);
87 }
88 
89 //###############################################################################
90 
92 { }
93 
94 //###############################################################################
95 
97 
98  m_outputFile = std::make_unique<TFile>(m_outputFileName.c_str(),"RECREATE");
99  m_outputFile->cd();
100  m_ooc.resize(0);
101 
102  mapparse();
103 
104  if ( m_NormalizationType == "Lin" ) {
105  ATH_MSG_INFO( "Using weighting proportional to E_calib" );
107  }
108  else if ( m_NormalizationType == "Log" ) {
109  ATH_MSG_INFO( "Using weighting proportional to log(E_calib)" );
111  }
112  else if ( m_NormalizationType == "NClus" ) {
113  ATH_MSG_INFO( "Using weighting proportional to 1/N_Clus_E_calib>0" );
115  }
116  else {
117  ATH_MSG_INFO( "Using constant weighting" );
119  }
120 
121  if ( m_ClassificationType == "None" ) {
122  ATH_MSG_INFO( "Expecting single particle input" );
124  }
125  else if ( m_ClassificationType == "ParticleID_EM" ) {
126  ATH_MSG_INFO( "Expecting ParticleID simulation as input -- use EM type clusters only" );
128  }
129  else if ( m_ClassificationType == "ParticleID_HAD" ) {
130  ATH_MSG_INFO( "Expecting ParticleID simulation as input -- use HAD type clusters only" );
132  }
133  else {
134  ATH_MSG_WARNING( " unknown classification type " << m_ClassificationType << " given! Using None instead" );
136  }
137 
138  int iside(-1);
139  int ieta(-1);
140  int iphi(-1);
141  int ilogE(-1);
142  int iloglambda(-1);
143  int iweight(-1);
144 
145  m_isampmap.resize(3,-1);
146  for(unsigned int idim=0;idim<m_dimensions.size();idim++) {
147  if ( m_dimensions[idim].title() == "side" ) {
148  iside = idim;
149  m_isampmap[0] = iside;
150  }
151  else if ( m_dimensions[idim].title() == "|eta|" )
152  ieta = idim;
153  else if ( m_dimensions[idim].title() == "phi" ) {
154  iphi = idim;
155  m_isampmap[1] = iphi;
156  }
157  else if ( m_dimensions[idim].title() == "log10(E_clus (MeV))" ) {
158  ilogE = idim;
159  m_isampmap[2] = ilogE;
160  }
161  else if ( m_dimensions[idim].title() == "log10(lambda_clus (mm))" )
162  iloglambda = idim;
163  else if ( m_dimensions[idim].title() == "weight" )
164  iweight = idim;
165  }
166  if ( ilogE < 0 || ieta < 0 || iloglambda < 0 || iweight < 0 || iside < 0 ) {
167  ATH_MSG_FATAL(" Mandatory dimension log10E, |eta|, log10lambda or weight missing ...");
168  return StatusCode::FAILURE;
169  }
170  int nside = m_dimensions[iside].bins();
171  int nphi = (iphi>=0?m_dimensions[iphi].bins():1);
172  int nlogE = m_dimensions[ilogE].bins();
173  m_ooc.resize(nside*nphi*nlogE,nullptr);
174  for ( int jside=0;jside<nside;jside++) {
175  for ( int jphi=0;jphi<nphi;jphi++) {
176  for(int jlogE=0;jlogE<nlogE;jlogE++) {
177  TString oname("ooc");
178  oname += "_iside_";
179  oname += jside;
180  oname += "_[";
181  oname += m_dimensions[iside].lowEdge();
182  oname += ",";
183  oname += m_dimensions[iside].highEdge();
184  oname += ",";
185  oname += nside;
186  oname += "]";
187  oname += "_iphi_";
188  oname += jphi;
189  oname += "_[";
190  oname += (iphi>=0?m_dimensions[iphi].lowEdge():-1);
191  oname += ",";
192  oname += (iphi>=0?m_dimensions[iphi].highEdge():-1);
193  oname += ",";
194  oname += nphi;
195  oname += "]";
196  oname += "_ilogE_";
197  oname += jlogE;
198  oname += "_[";
199  oname += m_dimensions[ilogE].lowEdge();
200  oname += ",";
201  oname += m_dimensions[ilogE].highEdge();
202  oname += ",";
203  oname += nlogE;
204  oname += "]";
205  int iO = jlogE*nphi*nside+jphi*nside+jside;
206  m_ooc[iO] = new TProfile2D(oname,oname,
207  m_dimensions[ieta].bins(),
208  m_dimensions[ieta].lowEdge(),
209  m_dimensions[ieta].highEdge(),
210  m_dimensions[iloglambda].bins(),
211  m_dimensions[iloglambda].lowEdge(),
212  m_dimensions[iloglambda].highEdge(),
213  m_dimensions[iweight].lowEdge(),
214  m_dimensions[iweight].highEdge());
215  m_ooc[iO]->SetXTitle("|#eta_{clus}|");
216  m_ooc[iO]->SetYTitle("log_{10}(#lambda_{clus} (mm))");
217  m_ooc[iO]->SetZTitle("E_{out of cluster} / E_{clus}^{EM-no-PS/Gap3} / Isolation");
218  }
219  }
220  }
221  //--- check sampling names to use exclude in correction
222  for (const std::string& name : m_invalidSamplingNames) {
223  int theSampling(CaloSampling::Unknown);
224  for (unsigned int jsamp = 0;jsamp< CaloSampling::Unknown; jsamp++) {
226  theSampling = jsamp;
227  break;
228  }
229  }
230  if ( theSampling == CaloSampling::Unknown ) {
231  msg(MSG::ERROR) << "Calorimeter sampling "
232  << name
233  << " is not a valid Calorimeter sampling name and will be ignored! "
234  << "Valid names are: ";
235  for (unsigned int jsamp = 0;jsamp< CaloSampling::Unknown; jsamp++) {
237  if ( jsamp < CaloSampling::Unknown-1)
238  msg() << ", ";
239  else
240  msg() << ".";
241  }
242  msg() << endmsg;
243  }
244  else {
245  m_invalidSamplings.insert(theSampling);
246  }
247  }
248 
249  msg(MSG::INFO) << "Samplings to exclude from the out-of-cluster weighting:";
250  for (const std::string& name : m_invalidSamplingNames)
251  msg() << " " << name;
252  msg() << endmsg;
253 
255 
256  return StatusCode::SUCCESS;
257 }
258 
259 //###############################################################################
260 
262 {
263  ATH_MSG_INFO( "Writing out histograms" );
264  m_outputFile->cd();
265  for(unsigned int i=0;i<m_ooc.size();i++) {
266  m_ooc[i]->Write();
267  }
268  m_outputFile->Close();
269 
270  return StatusCode::SUCCESS;
271 }
272 
273 //###############################################################################
274 
276 {
278 
279  // total calib hit energy of all clusters
280  double eCalibTot(0.);
281  double nClusECalibGt0 = 0.0;
282 
283  for (const xAOD::CaloCluster* theCluster : *cc) {
284  double eC=999;
285  if (!theCluster->retrieveMoment(xAOD::CaloCluster::ENG_CALIB_TOT,eC)) {
286  ATH_MSG_ERROR( "Failed to retrieve cluster moment ENG_CALIB_TOT" );
287  return StatusCode::FAILURE;
288  }
290  double emFrac=-999;
291  if (!theCluster->retrieveMoment(xAOD::CaloCluster::ENG_CALIB_FRAC_EM,emFrac)){
292  ATH_MSG_ERROR( "Failed to retrieve cluster moment ENG_CALIB_FAC_EM" );
293  return StatusCode::FAILURE;
294  }
296  eC = 0;
298  eC = 0;
299  }
300  eCalibTot += eC;
301  if ( eC > 0 ) {
302  nClusECalibGt0++;
303  }
304  }
305 
306  if ( eCalibTot > 0 ) {
307  const double inv_eCalibTot = 1. / eCalibTot;
308  const double inv_nClusECalibGt0 = 1. / nClusECalibGt0;
309  for (const xAOD::CaloCluster* pClus : *cc) {
310  double eng = pClus->e();
311 
313  double emFrac=-999;
314  if (!pClus->retrieveMoment(xAOD::CaloCluster::ENG_CALIB_FRAC_EM,emFrac)){
315  ATH_MSG_ERROR( "Failed to retrieve cluster moment ENG_CALIB_FAC_EM");
316  return StatusCode::FAILURE;
317  }
319  continue;
321  continue;
322  }
323 
324  // subtract the samplings to ignore from eng
325  for (int sampling : m_invalidSamplings) {
326  eng -= pClus->eSample((CaloSampling::CaloSample)(sampling));
327  }
328 
329  if ( eng > 0 ) {
330 
331  int iside = 0;
332  int iphi = 0;
333  int ilogE = 0;
334  int nside = 1;
335  int nphi = 1;
336  int nlogE = 1;
337 
338  if ( m_isampmap[0] >= 0 ) {
339  const Gaudi::Histo1DDef & hd = m_dimensions[m_isampmap[0]];
340  nside = hd.bins();
341  iside = (int)(nside*(((pClus->eta()<0?-1.0:1.0) - hd.lowEdge())
342  /(hd.highEdge()-hd.lowEdge())));
343  if ( iside < 0 || iside > nside-1 ) {
344  ATH_MSG_WARNING( " Side index out of bounds " <<
345  iside << " not in [0," << nside-1 << "]" );
346  iside = -1;
347  }
348  }
349 
350  if ( m_isampmap[1] >= 0 ) {
351  const Gaudi::Histo1DDef & hd = m_dimensions[m_isampmap[1]];
352  nphi = hd.bins();
353  iphi = (int)(nphi*((pClus->phi() - hd.lowEdge())
354  /(hd.highEdge()-hd.lowEdge())));
355  if ( iphi < 0 || iphi > nphi-1 ) {
356  ATH_MSG_WARNING( " Phi index out of bounds " <<
357  iphi << " not in [0," << nphi-1 << "]" );
358  iphi = -1;
359  }
360  }
361 
362  const Gaudi::Histo1DDef & hd = m_dimensions[m_isampmap[2]];
363  nlogE = hd.bins();
364  ilogE = (int)(nlogE*((log10(eng) - hd.lowEdge())
365  /(hd.highEdge()-hd.lowEdge())));
366  if ( ilogE >= 0 && ilogE < nlogE ) {
367  double lamb,eout,etot,isol;
368  if (!pClus->retrieveMoment(xAOD::CaloCluster::CENTER_LAMBDA,lamb) ||
369  !pClus->retrieveMoment(xAOD::CaloCluster::ENG_CALIB_OUT_L,eout) ||
370  !pClus->retrieveMoment(xAOD::CaloCluster::ENG_CALIB_TOT,etot) ||
371  !pClus->retrieveMoment(xAOD::CaloCluster::ISOLATION,isol)) {
372  ATH_MSG_ERROR( "Failed to retrieve a cluster moment (CENTER_LAMBDA,ENG_CALIB_OUT,ENG_CALIB_TOT,ISOLATION)" );
373  return StatusCode::FAILURE;
374  }
375 
376  if ( lamb > 0 &&
377  etot > 0 &&
378  isol > 0.5 )
379  {
380  int iO = ilogE*nphi*nside+iphi*nside+iside;
381  if (m_ooc[iO]) {
382  double norm = 0.0;
384  norm = etot*inv_eCalibTot;
385  }
387  // cluster has to have at least 1% of the calib hit E
388  norm = log10(etot*inv_eCalibTot)+2.0;
389  }
391  norm = inv_nClusECalibGt0;
392  }
393  else {
394  norm = 1.0;
395  }
396  if ( norm > 0 ) {
397  m_ooc[iO]->Fill(fabs(pClus->eta()),log10(lamb),eout/eng/isol,norm);
398  }
399  }
400  }
401  }
402  }
403  }
404  }
405 
406  return StatusCode::SUCCESS;
407 }
408 
409 void GetLCOutOfCluster::mapinsert(const std::vector<Gaudi::Histo1DDef> & dims) {
410  for (unsigned int i=0;i<dims.size();i++) {
411  m_dimensionsmap[dims[i].title()] = dims[i];
412  }
413 }
414 
416 
417  for (std::pair<const std::string, Gaudi::Histo1DDef>& p : m_dimensionsmap) {
418  m_dimensions.push_back(p.second);
419  ATH_MSG_DEBUG(" New Dimension: "
420  << p.second.title() << ", [" << p.second.lowEdge()
421  << ", " << p.second.highEdge()
422  << ", " << p.second.bins()
423  << "]");
424  }
425 }
426 
427 //###############################################################################
GetLCDefs::CONST
@ CONST
Definition: GetLCDefs.h:21
GetLCDefs::Unknown
@ Unknown
Definition: GetLCDefs.h:21
PlotCalibFromCool.norm
norm
Definition: PlotCalibFromCool.py:100
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
python.PerfMonSerializer.p
def p
Definition: PerfMonSerializer.py:743
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
GetLCOutOfCluster::m_NormalizationTypeNumber
int m_NormalizationTypeNumber
Definition: GetLCOutOfCluster.h:143
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
python.App.bins
bins
Definition: App.py:410
GetLCOutOfCluster::m_NormalizationType
std::string m_NormalizationType
string to choose different normalization types
Definition: GetLCOutOfCluster.h:141
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:70
AthCommonDataStore< AthCommonMsg< Algorithm > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T > &t)
Definition: AthCommonDataStore.h:145
GetLCDefs.h
GetLCOutOfCluster::m_ooc
std::vector< TProfile2D * > m_ooc
Vector of actual histograms.
Definition: GetLCOutOfCluster.h:96
TProfile2D
Definition: rootspy.cxx:531
M_PI
#define M_PI
Definition: ActiveFraction.h:11
xAOD::CaloCluster_v1::CENTER_LAMBDA
@ CENTER_LAMBDA
Shower depth at Cluster Centroid.
Definition: CaloCluster_v1.h:136
GetLCOutOfCluster::m_ClassificationType
std::string m_ClassificationType
string to choose different classification types
Definition: GetLCOutOfCluster.h:154
GetLCOutOfCluster::initialize
virtual StatusCode initialize()
Definition: GetLCOutOfCluster.cxx:96
GetLCOutOfCluster::m_dimensionsmap
std::map< std::string, Gaudi::Histo1DDef > m_dimensionsmap
property to set all dimensions introduced above
Definition: GetLCOutOfCluster.h:84
GetLCDefs::NONE
@ NONE
Definition: GetLCDefs.h:25
GetLCDefs::NCLUS
@ NCLUS
Definition: GetLCDefs.h:21
GetLCDefs::PARTICLEID_EM
@ PARTICLEID_EM
Definition: GetLCDefs.h:25
xAOD::CaloCluster_v1
Description of a calorimeter cluster.
Definition: CaloCluster_v1.h:59
GetLCOutOfCluster::m_invalidSamplingNames
std::vector< std::string > m_invalidSamplingNames
vector of names of the calorimeter samplings not to use when applying the out-of-cluster weights.
Definition: GetLCOutOfCluster.h:122
GetLCOutOfCluster::finalize
virtual StatusCode finalize()
Definition: GetLCOutOfCluster.cxx:261
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
lumiFormat.i
int i
Definition: lumiFormat.py:92
CaloSampling::CaloSample
CaloSample
Definition: Calorimeter/CaloGeoHelpers/CaloGeoHelpers/CaloSampling.h:22
GetLCOutOfCluster::m_outputFile
std::unique_ptr< TFile > m_outputFile
Output file to save histograms in.
Definition: GetLCOutOfCluster.h:109
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
GetLCOutOfCluster::m_isampmap
std::vector< int > m_isampmap
Vector of indices in m_dimensions.
Definition: GetLCOutOfCluster.h:90
xAOD::CaloCluster_v1::ENG_CALIB_TOT
@ ENG_CALIB_TOT
Calibration Hit energy inside the cluster.
Definition: CaloCluster_v1.h:195
covarianceTool.title
title
Definition: covarianceTool.py:542
GetLCOutOfCluster.h
xAOD::CaloCluster_v1::ENG_CALIB_FRAC_EM
@ ENG_CALIB_FRAC_EM
Calibration Hit energy inside the cluster caused by e/gamma/pi0.
Definition: CaloCluster_v1.h:248
xAOD::CaloCluster_v1::ISOLATION
@ ISOLATION
Energy weighted fraction of non-clustered perimeter cells.
Definition: CaloCluster_v1.h:146
GetLCOutOfCluster::m_clusterCollName
SG::ReadHandleKey< xAOD::CaloClusterContainer > m_clusterCollName
Name of the CaloClusterContainer to use.
Definition: GetLCOutOfCluster.h:113
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
CaloSamplingHelper.h
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
AthAlgorithm
Definition: AthAlgorithm.h:47
GetLCOutOfCluster::execute
virtual StatusCode execute()
Definition: GetLCOutOfCluster.cxx:275
GetLCOutOfCluster::mapparse
void mapparse()
Definition: GetLCOutOfCluster.cxx:415
GetLCOutOfCluster::GetLCOutOfCluster
GetLCOutOfCluster(const std::string &name, ISvcLocator *pSvcLocator)
Definition: GetLCOutOfCluster.cxx:41
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
errorcheck.h
Helpers for checking error return status codes and reporting errors.
GetLCOutOfCluster::m_outputFileName
std::string m_outputFileName
Name of the output file to save histograms in.
Definition: GetLCOutOfCluster.h:103
GetLCOutOfCluster::~GetLCOutOfCluster
virtual ~GetLCOutOfCluster()
Definition: GetLCOutOfCluster.cxx:91
GetLCDefs::PARTICLEID_HAD
@ PARTICLEID_HAD
Definition: GetLCDefs.h:25
GetLCOutOfCluster::m_invalidSamplings
std::set< int > m_invalidSamplings
actual set of samplings to be ignored for out-of-cluster weights
Definition: GetLCOutOfCluster.h:129
CaloSamplingHelper::getSamplingName
static const std::string & getSamplingName(const CaloSampling::CaloSample theSample)
Returns a string (name) for each CaloSampling.
Definition: CaloUtils/src/CaloSamplingHelper.cxx:42
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
AthCommonMsg< Algorithm >::msg
MsgStream & msg() const
Definition: AthCommonMsg.h:24
GetLCDefs::LOG
@ LOG
Definition: GetLCDefs.h:21
CaloClusterContainer.h
GetLCDefs::LIN
@ LIN
Definition: GetLCDefs.h:21
xAOD::CaloCluster_v1::ENG_CALIB_OUT_L
@ ENG_CALIB_OUT_L
Attached Calibration Hit energy outside clusters but inside the calorimeter with loose matching (Angl...
Definition: CaloCluster_v1.h:196
GetLCOutOfCluster::m_ClassificationTypeNumber
int m_ClassificationTypeNumber
Definition: GetLCOutOfCluster.h:156
GetLCOutOfCluster::m_dimensions
std::vector< Gaudi::Histo1DDef > m_dimensions
definition of all dimensions used for out-of-cluster corrections
Definition: GetLCOutOfCluster.h:76
ReadHandle.h
Handle class for reading from StoreGate.
GetLCOutOfCluster::mapinsert
void mapinsert(const std::vector< Gaudi::Histo1DDef > &dims)
Definition: GetLCOutOfCluster.cxx:409
python.handimod.cc
int cc
Definition: handimod.py:523