ATLAS Offline Software
Loading...
Searching...
No Matches
GetLCDeadMaterialTree.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: GetLCDeadMaterialTree.cxx,v 1.3 2009-05-18 20:31:52 pospelov Exp $
8//
9// Description: see GetLCDeadMaterialTree.h
10//
11// Environment:
12// Software developed for the ATLAS Detector at CERN LHC
13//
14// Author List:
15// Gennady Pospelov
16//
17//-----------------------------------------------------------------------
18
19//-----------------------
20// This Class's Header --
21//-----------------------
23
24//---------------
25// C++ Headers --
26//---------------
29#include "GaudiKernel/ISvcLocator.h"
30#include "GaudiKernel/StatusCode.h"
31
33#include "CaloEvent/CaloCell.h"
38#include <CLHEP/Units/SystemOfUnits.h>
46
47#include "TFile.h"
48#include "TTree.h"
49#include "TString.h"
50#include <iterator>
51#include <cmath>
52
53using CLHEP::MeV;
54using CLHEP::TeV;
55
56
57//###############################################################################
59 ISvcLocator* pSvcLocator)
60 : AthAlgorithm(name, pSvcLocator),
61 m_HadDMCoeffInitFile("CaloHadDMCoeff_init_v2.txt"),
62 m_outputTree(nullptr),
63 m_outputFileName("DeadMaterialTree.root"),
64 m_outputFile(nullptr),
65 m_clusterCollName("CaloTopoClusters"),
66 m_HadDMCoeff(nullptr),
67 m_data(nullptr),
69 m_energyMin(200*MeV),
70 m_calo_id(nullptr)
71{
72
73 // dead material zone description
74 declareProperty("HadDMCoeffInitFile",m_HadDMCoeffInitFile);
75
76 // Name of output file to save histograms in
77 declareProperty("OutputFileName",m_outputFileName);
78
79 // Name of ClusterContainer (uncalibrated) to use
80 declareProperty("ClusterCollectionName",m_clusterCollName);
81
82 // Name of ClusterContainer (calibrated) to use
83 declareProperty("ClusterCollectionNameCalib",m_clusterCollNameCalib);
84
85 // to save additional info from the collection with calibrated clusters
86 declareProperty("doSaveCalibClusInfo", m_doSaveCalibClusInfo);
87
88}
89
90
91
92/* ****************************************************************************
93
94***************************************************************************** */
99
100
101
102/* ****************************************************************************
103
104***************************************************************************** */
106{
107 ATH_CHECK(detStore()->retrieve(m_calo_id, "CaloCell_ID"));
108
109 /* ********************************************
110 set list of valid moments
111 ******************************************** */
112 moment_name_vector validNames;
113 validNames.push_back(moment_name_pair(std::string("ENG_CALIB_DEAD_EMB0"),xAOD::CaloCluster::ENG_CALIB_DEAD_EMB0));
114 validNames.push_back(moment_name_pair(std::string("ENG_CALIB_DEAD_TILE0"),xAOD::CaloCluster::ENG_CALIB_DEAD_TILE0));
115 validNames.push_back(moment_name_pair(std::string("ENG_CALIB_DEAD_TILEG3"),xAOD::CaloCluster::ENG_CALIB_DEAD_TILEG3));
116 validNames.push_back(moment_name_pair(std::string("ENG_CALIB_DEAD_EME0"),xAOD::CaloCluster::ENG_CALIB_DEAD_EME0));
117 validNames.push_back(moment_name_pair(std::string("ENG_CALIB_DEAD_HEC0"),xAOD::CaloCluster::ENG_CALIB_DEAD_HEC0));
118 validNames.push_back(moment_name_pair(std::string("ENG_CALIB_DEAD_FCAL"),xAOD::CaloCluster::ENG_CALIB_DEAD_FCAL));
119 validNames.push_back(moment_name_pair(std::string("ENG_CALIB_DEAD_LEAKAGE"),xAOD::CaloCluster::ENG_CALIB_DEAD_LEAKAGE));
120 validNames.push_back(moment_name_pair(std::string("ENG_CALIB_DEAD_UNCLASS"),xAOD::CaloCluster::ENG_CALIB_DEAD_UNCLASS));
121
122 /* ********************************************
123 initial coefficients
124 ******************************************** */
126 std::string fileName = PathResolver::find_file (m_HadDMCoeffInitFile, "DATAPATH");
127 m_HadDMCoeff = dmHelper.InitDataFromFile(fileName.c_str());
128 if( !m_HadDMCoeff ) {
129 ATH_MSG_FATAL( " Error while initializing default dead material coefficients " );
130 return StatusCode::FAILURE;
131 }
132 // how we have to set correspondance between dead material areas and calibration moments
133 m_momentForDMArea.resize( m_HadDMCoeff->getSizeAreaSet());
134 for(int i_dm=0; i_dm<m_HadDMCoeff->getSizeAreaSet(); i_dm++){
135 bool isValid(false);
136 for (const moment_name_pair& vname : validNames) {
137 if ( m_HadDMCoeff->getArea(i_dm)->getTitle() == vname.first ) {
138 m_momentForDMArea[i_dm] = vname.second;
139 isValid = true;
140 break;
141 }
142 }
143 if ( !isValid) {
144 ATH_MSG_FATAL( " Unknown moment name '" << m_HadDMCoeff->getArea(i_dm)->getTitle() << "' in the m_HadDMCoeff!" );
145 return StatusCode::FAILURE;
146 }
147 }
148
149 /* ********************************************
150 output file&tree
151 ******************************************** */
152 m_data = new CaloHadDMCoeffData(nullptr);
153
154 m_outputFile = new TFile(m_outputFileName.c_str(),"RECREATE");
155 m_outputFile->cd();
156
157 m_outputTree = m_data->MakeTree("DeadMaterialTree");
158
159 ATH_CHECK( m_clusterCollName.initialize() );
161 ATH_CHECK( m_clusterCollNameCalib.initialize() );
162 }
163 else {
165 }
166
167 return StatusCode::SUCCESS;
168}
169
170
171
172/* ****************************************************************************
173
174***************************************************************************** */
176{
177 ATH_MSG_INFO( "Writing out tree" );
178 m_outputFile->cd();
179 m_outputTree->Write();
180 m_outputFile->Close();
181
182 return StatusCode::SUCCESS;
183}
184
185
186
187/* ****************************************************************************
188
189***************************************************************************** */
190StatusCode GetLCDeadMaterialTree::execute(const EventContext& ctx)
191{
192 //bool useLink = true;
193
194 /* ********************************************
195 access to cluster container
196 ******************************************** */
198
199 /* ********************************************
200 reading primary particle
201 ******************************************** */
202 const McEventCollection* truthEvent=nullptr;
203 ATH_CHECK( evtStore()->retrieve(truthEvent, "TruthEvent") );
204 const HepMC::ConstGenParticlePtr& gen = truthEvent->at(0)->particles().front();
205
206 double mc_eta = gen->momentum().pseudoRapidity();
207 double mc_phi = gen->momentum().phi();
208
209 m_data->clear();
210
211 m_data->m_mc_pdg = gen->pdg_id();
212 m_data->m_mc_ener = gen->momentum().e();
213 m_data->m_mc_eta = mc_eta;
214 m_data->m_mc_phi = mc_phi;
215
216 int nClus = pClusColl->size();
217 m_data->m_ncls = nClus;
218 m_data->m_cls_ener->resize(nClus, 0.0);
219 m_data->m_cls_ener_unw->resize(nClus, 0.0);
220 m_data->m_cls_lambda->resize(nClus, 0.0);
221 m_data->m_cls_eta->resize(nClus, 0.0);
222 m_data->m_cls_phi->resize(nClus, 0.0);
223 //m_data->m_cls_emfrac->resize(nClus, 0.0);
224 m_data->m_cls_smpener->resize(nClus);
225 m_data->m_cls_smpener_unw->resize(nClus);
226 //m_data->m_cls_ibin->resize(nClus);
227 m_data->m_cls_eprep->resize(nClus);
228 m_data->m_cls_dmener->resize(nClus);
229 m_data->m_narea = m_HadDMCoeff->getSizeAreaSet();
230 for(int i_cls=0; i_cls<nClus; i_cls++){
231 //(*m_cls_ibin)[i_cls].resize(m_narea, -1);
232 (*m_data->m_cls_smpener)[i_cls].resize(CaloSampling::Unknown, 0.0);
233 (*m_data->m_cls_smpener_unw)[i_cls].resize(CaloSampling::Unknown, 0.0);
234 (*m_data->m_cls_eprep)[i_cls].resize(m_data->m_narea, 0.0);
235 (*m_data->m_cls_dmener)[i_cls].resize(m_data->m_narea, 0.0);
236 }
237 m_data->m_cls_engcalib->resize(nClus, 0.0);
238 m_data->m_cls_recostat->resize(nClus, 0);
239 m_data->m_cls_pi0prob->resize(nClus, 0.0);
240 m_data->m_cls_isol->resize(nClus, 0.0);
241 m_data->m_cls_oocener->resize(nClus, 0.0);
242 m_data->m_cls_calib_emfrac->resize(nClus, 0.0);
243 m_data->m_cls_engcalibpres->resize(nClus, 0.0);
244
245 xAOD::CaloClusterContainer::const_iterator clusIter = pClusColl->begin();
246 xAOD::CaloClusterContainer::const_iterator clusIterEnd = pClusColl->end();
247 unsigned int iClus = 0;
248 for( ;clusIter!=clusIterEnd;++clusIter,++iClus) {
249 const xAOD::CaloCluster * theCluster = (*clusIter);
250
251 (*m_data->m_cls_ener)[iClus] = theCluster->e();
252 // cluster energy in samplings
253 for(int i_smp=0; i_smp<(int)CaloSampling::Unknown; i_smp++){
254 (*m_data->m_cls_smpener)[iClus][i_smp] = theCluster->eSample((CaloSampling::CaloSample)i_smp);
255 }
256
257 // calibration energy of clusters
258 double mx_calib_tot=0;
259 if( !theCluster->retrieveMoment( xAOD::CaloCluster::ENG_CALIB_TOT, mx_calib_tot) ) {
260 ATH_MSG_ERROR( "Moment ENG_CALIB_TOT is absent" );
261 return StatusCode::FAILURE;
262 }
263 m_data->m_engClusSumCalib += mx_calib_tot;
264 (*m_data->m_cls_engcalib)[iClus] = mx_calib_tot;
265
266 double mx_calib_emb0=0, mx_calib_eme0=0, mx_calib_tileg3=0;
267 if( !theCluster->retrieveMoment(xAOD::CaloCluster::ENG_CALIB_EMB0, mx_calib_emb0)
268 || !theCluster->retrieveMoment(xAOD::CaloCluster::ENG_CALIB_EME0, mx_calib_eme0)
269 || !theCluster->retrieveMoment(xAOD::CaloCluster::ENG_CALIB_TILEG3, mx_calib_tileg3)){
270 ATH_MSG_ERROR( "One of the moment ENG_CALIB_EMB0, ENG_CALIB_EME0, ENG_CALIB_TILEG3 is absent" );
271 return StatusCode::FAILURE;
272 }else{
273 (*m_data->m_cls_engcalibpres)[iClus] = (mx_calib_emb0+mx_calib_eme0+mx_calib_tileg3);
274 }
275
278 if(pClusColl->size() != pClusCollCalib->size()) {
279 ATH_MSG_WARNING( "Different size of calibrated and uncalibrated cluster collection "
280 << pClusColl->size() << " " << pClusCollCalib->size() );
281 return StatusCode::SUCCESS;
282 }
283
284 const xAOD::CaloCluster * theClusterCalib = pClusCollCalib->at(iClus);
285
286 // reco status
287 const CaloRecoStatus& recoStatus = theClusterCalib->recoStatus();
288
289 (*m_data->m_cls_recostat)[iClus] = recoStatus.getStatusWord();
290
291 // classification pi0 probability (available on calibrated cluster)
292 double pi0Prob = 0;
293 if( !theClusterCalib->retrieveMoment( xAOD::CaloCluster::EM_PROBABILITY, pi0Prob) ) {
294 //ATH_MSG_ERROR( "Moment ENG_CALIB_TOT is absent" );
295 pi0Prob = -1.0;
296 } else {
297 if ( pi0Prob < 0 ) pi0Prob = 0;
298 if ( pi0Prob > 1 ) pi0Prob = 1;
299 }
300 (*m_data->m_cls_pi0prob)[iClus] = pi0Prob;
301 } // m_doSaveCalibClusInfo
302
303 // cluster isolation moment and out of cluster energy
304 double mx_isol;
305 if ( !theCluster->retrieveMoment(xAOD::CaloCluster::ISOLATION, mx_isol)) {
306 ATH_MSG_ERROR( "Moment ISOLATION is absent" );
307 return StatusCode::FAILURE;
308 }else{
309 (*m_data->m_cls_isol)[iClus] = mx_isol;
310 }
311
312 double mx_calib_oocL;
313 if ( !theCluster->retrieveMoment(xAOD::CaloCluster::ENG_CALIB_OUT_L, mx_calib_oocL)) {
314 ATH_MSG_ERROR( "Moment ENG_CALIB_OUT_L is absent" );
315 return StatusCode::FAILURE;
316 }else{
317 (*m_data->m_cls_oocener)[iClus] = mx_calib_oocL;
318 }
319
320 double mx_calib_emfrac;
321 if ( !theCluster->retrieveMoment(xAOD::CaloCluster::ENG_CALIB_FRAC_EM, mx_calib_emfrac)) {
322 ATH_MSG_WARNING( "Moment ENG_CALIB_FRAC_EM is absent" );
323 return StatusCode::FAILURE;
324 }else{
325 (*m_data->m_cls_calib_emfrac)[iClus] = mx_calib_emfrac;
326 }
327
328
329 // calculation of cluster energy and energy in samplings without accounting
330 // cells weights
331 xAOD::CaloCluster::const_cell_iterator cellIter = theCluster->cell_begin();
332 xAOD::CaloCluster::const_cell_iterator cellIterEnd = theCluster->cell_end();
333 for(; cellIter != cellIterEnd; cellIter++ ){
334 const CaloCell* pCell = (*cellIter);
335 Identifier myId = pCell->ID();
337 (*m_data->m_cls_ener_unw)[iClus] += pCell->e();
338 (*m_data->m_cls_smpener_unw)[iClus][(int)nsmp] += pCell->e();
339 }
340
341 double clusEner = (*m_data->m_cls_ener_unw)[iClus];
342 double clusLambda=0;
343 if (!theCluster->retrieveMoment(xAOD::CaloCluster::CENTER_LAMBDA,clusLambda)) {
344 ATH_MSG_WARNING( "Moment CENTER_LAMBDA is absent" );
345 return StatusCode::FAILURE;
346 }
347 (*m_data->m_cls_lambda)[iClus] = clusLambda;
348 (*m_data->m_cls_eta)[iClus] = theCluster->eta();
349 (*m_data->m_cls_phi)[iClus] = theCluster->phi();
350 if(clusEner > m_energyMin ) {
351 //clusEner = log10(clusEner);
352 //if(clusEner > 6.3) clusEner = 6.2999;
353 //clusLambda = log10(clusLambda);
354 //if(clusLambda > 4.0) clusLambda = 3.9999;
355 //double clusEta=fabs(theCluster->eta());
356
357 for(int i_dma=0; i_dma<m_data->m_narea; i_dma++){
358 //(*m_cls_ibin)[iClus][i_dma] = m_HadDMCoeff->getBin(i_dma, (float)clusEmFrac, (float)clusEner, (float)clusLambda, (float)clusEta);
359 double dmVal=0;
360 if (!theCluster->retrieveMoment( m_momentForDMArea[i_dma],dmVal)) {
361 ATH_MSG_WARNING( "Moment "<< m_momentForDMArea[i_dma] << " is absent" );
362 return StatusCode::FAILURE;
363 }
364 (*m_data->m_cls_dmener)[iClus][i_dma] = dmVal;
365
366 // now we have to calculate cluster quantities which we will use later for
367 // reconstruction of given dead material calibration moment
368 double eprep = 0.0;
369 double x(0), y(0);
370 switch ( m_momentForDMArea[i_dma] ) {
372 x = (*m_data->m_cls_smpener_unw)[iClus][CaloSampling::PreSamplerB];
373 if(x > 0.0) {
374 eprep = x;
375 }
376 break;
378 x = (*m_data->m_cls_smpener_unw)[iClus][CaloSampling::EMB3];
379 y = (*m_data->m_cls_smpener_unw)[iClus][CaloSampling::TileBar0];
380 if(x>0.0 && y>0.0) {
381 eprep = sqrt(x*y);
382 }
383 break;
385 x = (*m_data->m_cls_smpener_unw)[iClus][CaloSampling::TileGap3];
386 if(x > 0.0) {
387 eprep = x;
388 }
389 break;
391 x = (*m_data->m_cls_smpener_unw)[iClus][CaloSampling::PreSamplerE];
392 if( x > 0.0 ) {
393 eprep = x;
394 }
395 break;
397 x = (*m_data->m_cls_smpener_unw)[iClus][CaloSampling::EME3];
398 y = (*m_data->m_cls_smpener_unw)[iClus][CaloSampling::HEC0];
399 if(x>0.0 && y>0.0) {
400 eprep = sqrt(x*y);
401 }
402 break;
404 eprep = (*m_data->m_cls_ener_unw)[iClus];
405 break;
407 eprep = (*m_data->m_cls_ener_unw)[iClus];
408 break;
410 eprep = (*m_data->m_cls_ener_unw)[iClus];
411 break;
412 default:
413 ATH_MSG_ERROR( "No such moment registered " << m_momentForDMArea[i_dma] );
414 return StatusCode::FAILURE;
415 break;
416 }
417 (*m_data->m_cls_eprep)[iClus][i_dma] = eprep;
418
419 } // loop over dm areas
420
421 } // good cluster
422 } // loop over clusters
423
424 // now we have to process special case, when we have DM energy, say, in front of the
425 // calorimeter but there is no signal in presampler itself. When we have to add this
426 // DM energy into 'unclassified' area
427 for(int i_cls=0; i_cls<m_data->m_ncls; i_cls++){
428 double edm_uncorrected = 0.0;
429 for(int i_dma=0; i_dma<m_data->m_narea; i_dma++){
431 if( (*m_data->m_cls_eprep)[i_cls][i_dma] <= 0.0 &&
437 {
438 edm_uncorrected += (*m_data->m_cls_dmener)[i_cls][i_dma];
439 (*m_data->m_cls_dmener)[i_cls][i_dma] = 0.0;
440 }
441 } // i_dma
442 // now let's put this energy into unclassified area
443 for(int i_dma=0; i_dma<m_data->m_narea; i_dma++){
445 (*m_data->m_cls_dmener)[i_cls][i_dma] += edm_uncorrected;
446 }
447 } // i_dma
448 } // i_cls
449
450 m_outputTree->Fill();
451
452 return StatusCode::SUCCESS;
453}
454
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_WARNING(x)
Helpers for checking error return status codes and reporting errors.
static const double MeV
Handle class for reading from StoreGate.
#define y
#define x
AthAlgorithm(const std::string &name, ISvcLocator *pSvcLocator)
Constructor.
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
ServiceHandle< StoreGateSvc > & evtStore()
const ServiceHandle< StoreGateSvc > & detStore() const
Data object for each calorimeter readout cell.
Definition CaloCell.h:57
virtual double e() const override final
get energy (data member) (synonym to method energy()
Definition CaloCell.h:333
Identifier ID() const
get ID (from cached data member) non-virtual and inline for fast access
Definition CaloCell.h:295
Data to read from special DeadMaterialTree.
CaloLocalHadCoeff * InitDataFromFile(const char *fname)
reconstruction status indicator
virtual const store_type & getStatusWord() const
retrieve the entire status word
DataModel_detail::const_iterator< DataVector > const_iterator
Definition DataVector.h:838
const T * at(size_type n) const
Access an element, as an rvalue.
CaloLocalHadCoeff * m_HadDMCoeff
Collection of dead material correction coeffitients.
std::string m_outputFileName
Name of the output file to save tree in.
SG::ReadHandleKey< xAOD::CaloClusterContainer > m_clusterCollNameCalib
Name of the calibrated CaloClusterContainer to use.
virtual StatusCode execute(const EventContext &ctx)
Execute method.
virtual StatusCode initialize()
std::pair< std::string, xAOD::CaloCluster::MomentType > moment_name_pair
std::vector< moment_name_pair > moment_name_vector
const CaloCell_ID * m_calo_id
bool m_doSaveCalibClusInfo
save additional cluster info from calibrated collections
TTree * m_outputTree
Output tree.
std::string m_HadDMCoeffInitFile
Name of text file with initial parameters for coefficients calculation.
GetLCDeadMaterialTree(const std::string &name, ISvcLocator *pSvcLocator)
CaloHadDMCoeffData * m_data
data to save into the tree
SG::ReadHandleKey< xAOD::CaloClusterContainer > m_clusterCollName
Name of the uncalibrated CaloClusterContainer to use.
std::vector< xAOD::CaloCluster::MomentType > m_momentForDMArea
virtual StatusCode finalize()
TFile * m_outputFile
Output file to save tree in.
This defines the McEventCollection, which is really just an ObjectVector of McEvent objectsFile: Gene...
static std::string find_file(const std::string &logical_file_name, const std::string &search_path)
bool retrieveMoment(MomentType type, double &value) const
Retrieve individual moment.
virtual double eta() const
The pseudorapidity ( ) of the particle.
virtual double e() const
The total energy of the particle.
CaloClusterCellLink::const_iterator const_cell_iterator
Iterator of the underlying CaloClusterCellLink (explicitly const version).
const_cell_iterator cell_end() const
float eSample(const CaloSample sampling) const
virtual double phi() const
The azimuthal angle ( ) of the particle.
MomentType
Enums to identify different moments.
@ ENG_CALIB_OUT_L
Attached Calibration Hit energy outside clusters but inside the calorimeter with loose matching (Angl...
@ EM_PROBABILITY
Classification probability to be em-like.
@ ENG_CALIB_DEAD_UNCLASS
Attached Calibration Hit energy in dead material in unclassified areas of the detector.
@ ENG_CALIB_DEAD_HEC0
Attached Calibration Hit energy in dead material between EME3 and HEC0.
@ ENG_CALIB_DEAD_TILEG3
Attached Calibration Hit energy in dead material before scintillator.
@ CENTER_LAMBDA
Shower depth at Cluster Centroid.
@ ENG_CALIB_DEAD_EME0
Attached Calibration Hit energy in dead material before EME0, between EME0 and EME1.
@ ENG_CALIB_DEAD_TILE0
Attached Calibration Hit energy in dead material between EMB3 and TILE0.
@ ENG_CALIB_FRAC_EM
Calibration Hit energy inside the cluster caused by e/gamma/pi0.
@ ENG_CALIB_DEAD_FCAL
Attached Calibration Hit energy in dead material before FCAL, between FCAL and HEC.
@ ENG_CALIB_TOT
Calibration Hit energy inside the cluster.
@ ENG_CALIB_DEAD_LEAKAGE
Attached Calibration Hit energy in dead material behind calorimeters.
@ ENG_CALIB_EMB0
Calibration Hit energy inside the cluster barrel presampler.
@ ENG_CALIB_EME0
Calibration Hit energy inside the cluster endcap presampler.
@ ENG_CALIB_DEAD_EMB0
Attached Calibration Hit energy in dead material before EMB0, between EMB0 and EMB1.
@ ISOLATION
Energy weighted fraction of non-clustered perimeter cells.
@ ENG_CALIB_TILEG3
Calibration Hit energy inside the cluster scintillator.
const_cell_iterator cell_begin() const
Iterator of the underlying CaloClusterCellLink (const version).
CaloRecoStatus & recoStatus()
Accesssor to CaloRecoStatus (non-const).
HepMC3::ConstGenParticlePtr ConstGenParticlePtr
Definition GenParticle.h:20
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.