ATLAS Offline Software
Loading...
Searching...
No Matches
CaloClusterROIPhiRZContainerMaker.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4
7
10
12#include "TrkSurfaces/Surface.h"
13
14
15#include <stdexcept>
16#include <algorithm>
17#include <cstdint>
18
19namespace {
20 constexpr float PI_F = static_cast<float>(M_PI);
21}
22
23namespace InDet {
25 ISvcLocator* pSvcLocator):
26 AthReentrantAlgorithm(name, pSvcLocator)
27{
28}
29
30// ================================================================
32= default;
33
34// =================================================================
36{
38 ATH_CHECK( m_calosurf.retrieve() );
39 ATH_CHECK( m_caloMgrKey.initialize() );
40
41 if (m_outputClusterContainerName.empty()) {
42 ATH_MSG_FATAL( "No OutputROIContainerName given.");
43 return StatusCode::FAILURE;
44 }
45 if (m_outputClusterContainerName.size() > std::numeric_limits<uint8_t>::max()) {
46 ATH_MSG_FATAL( "Too many OutputROIContainerNames given.");
47 return StatusCode::FAILURE;
48 }
49 if (m_minPtEm.size() != m_phiWidth.size() || m_minPtEm.size() != m_outputClusterContainerName.size() ) {
50 ATH_MSG_FATAL( "Number of entries in minPt, phiWidth must match number of entries in OutputROIContainerName.");
51 return StatusCode::FAILURE;
52 }
53 m_outputIndex.reserve(m_minPtEm.size());
55 for (unsigned int idx=0; idx<m_minPtEm.size(); ++idx) {
56 m_outputIndex.push_back(idx);
58 }
59 std::sort(m_outputIndex.begin(),m_outputIndex.end(), [this](unsigned int idx_a, unsigned int idx_b) { return this->m_minPtEm[idx_a] < this->m_minPtEm[idx_b];});
60 m_sortedMinPtEm.reserve( m_outputIndex.size());
61 for (unsigned int idx : m_outputIndex) {
62 m_sortedMinPtEm.push_back( m_minPtEm[idx] );
63 }
64
67
70 m_outputSorted.reserve( m_outputIndex.size() );
71 m_outputUnsorted.reserve( m_outputIndex.size() );
72 for (unsigned int output_i=0; output_i<m_outputIndex.size(); ++output_i) {
73 if (m_phiWidth[m_outputIndex[output_i]]>0.) {
74 m_outputSorted.push_back(output_i);
75 }
76 else {
77 m_outputUnsorted.push_back(output_i);
78 }
79 ATH_MSG_DEBUG( "ROIPhiRZ container " << m_outputClusterContainerName[ m_outputIndex[output_i] ]
80 << " : " << m_minPtEm[m_outputIndex[output_i] ] << " MeV " << ( m_phiWidth[m_outputIndex[output_i]]>0. ? " order by phi " : " unordered" ) );
81 }
82 return StatusCode::SUCCESS;
83}
84
85
86
87// ====================================================================
89{
90 //
91 // finalize method
92 //
93 ATH_MSG_DEBUG ("AllClusters " << m_allClusters << " selected " << m_selectedClusters << " max ROIs per event " << m_maxNROIs);
94
95 return StatusCode::SUCCESS;
96}
97
98// ======================================================================
99StatusCode CaloClusterROIPhiRZContainerMaker::execute(const EventContext& ctx) const
100{
101
102 if (m_inputClusterContainerName.key().empty()) {
103 return StatusCode::SUCCESS;
104 }
105
106 // retrieve cluster containers, return `failure' if not existing
108 ATH_CHECK(inputClusterContainer.isValid());
109
111 ATH_CHECK(caloMgrHandle.isValid());
112 const CaloDetDescrManager *caloMgr = caloMgrHandle.cptr();
113
114 unsigned int all_clusters{};
115 unsigned int selected_clusters{};
116 ROIPhiRZContainer rois; // temporary ROI container
117 std::vector<unsigned int > n_rois; // number of ROIs per output container
118 n_rois.resize(m_outputIndex.size(),0);
119
120 std::vector<uint8_t > max_output;// the outputs are ordered by the pt-cut, this is the index of the last output which passed the pt-cut per ROI
121 rois.reserve( inputClusterContainer->size());
122 max_output.resize(inputClusterContainer->size());
123
124 // create ROIs.
125 // first they are only stored in the temporary container
126 for(const xAOD::CaloCluster* cluster : *inputClusterContainer )
127 {
128 all_clusters++;
129 if (m_egammaCaloClusterSelector->passSelection(cluster,*caloMgr))
130 {
131 selected_clusters++;
132 addROI(*cluster, *caloMgr, rois, max_output, n_rois);
133 }
134 }
135 // This may happen if a ROI close to +-pi gets duplicated...
136 // so don't warn. See ATLASRECTS-7160.
137 //if (rois.size() > inputClusterContainer->size() ) {
138 // ATH_MSG_INFO( "Did not reserve enough storage for " << m_outputClusterContainerName[m_outputIndex[0]].key() );
139 //}
140
141
142 // create ROI output container
143 std::vector< SG::WriteHandle<ROIPhiRZContainer> > output_rois;
144 output_rois.reserve(m_outputIndex.size());
145 for (unsigned int output_idx : m_outputIndex) {
146 unsigned int the_size = n_rois[output_rois.size()];
147 output_rois.emplace_back( m_outputClusterContainerName[output_idx], ctx);
148 ATH_CHECK( output_rois.back().record( std::make_unique<ROIPhiRZContainer>() ) );
149 output_rois.back()->reserve( the_size);
150 }
151
152 if (!m_outputSorted.empty()) {
153 // sort ROIs by phi
154 std::vector<unsigned int> roi_order;
155 roi_order.reserve( rois.size() );
156 for (unsigned int idx=0; idx< rois.size(); ++idx) { roi_order.push_back( idx ); }
157 std::sort(roi_order.begin(),roi_order.end(),[&rois](unsigned int a, unsigned int b) { return rois[a][0] < rois[b][0]; });
158 // copy ROIs in sort order to output container which are to be sorted
159 for (unsigned int roi_i : roi_order) {
160 for (unsigned int output_i : m_outputSorted) {
161 if (output_i>=max_output[roi_i]) break;
162 output_rois[output_i]->push_back( rois[ roi_i ] );
163 }
164 }
165 }
166
167 // copy ROIs in original order to output container which should have the original order
168 // also remove duplicates
169 if (!m_outputUnsorted.empty()) {
170 for (unsigned int roi_unordered_i=0; roi_unordered_i < rois.size(); ++roi_unordered_i) {
171 for (unsigned int output_i : m_outputUnsorted) {
172 if (output_i>=max_output[roi_unordered_i]) break;
173 if (std::abs(rois[ roi_unordered_i ][0])<PI_F or (rois[ roi_unordered_i ][0] == PI_F)) {
174 output_rois[output_i]->push_back( rois[ roi_unordered_i ] );
175 }
176 }
177 }
178 }
179
180 // gather statistics
181 {
182 unsigned int max_size;
183 do {
184 max_size = m_maxNROIs;
185 } while (rois.size()>max_size && ! m_maxNROIs.compare_exchange_weak(max_size, rois.size()));
186 }
187 m_allClusters += all_clusters;
188 m_selectedClusters += selected_clusters;
189 return StatusCode::SUCCESS;
190}
191
193 const Trk::Surface &surf)
194{
195
196 Amg::Vector3D surfRefPoint = surf.globalReferencePoint();
197
198 double eta = cluster.eta();
199 double theta = 2 * atan(exp(-eta)); // -log(tan(theta/2));
200 double tantheta = tan(theta);
201 double phi = cluster.phi();
202
203 if (xAOD::EgammaHelpers::isBarrel(&cluster)) {
204 // Two corindate in a cyclinder are
205 // Trk::locRPhi = 0 (ie phi)
206 // Trk::locZ = 1(ie z)
207 double r = surfRefPoint.perp();
208 double z = tantheta == 0 ? 0. : r / tantheta;
211 return Trk::LocalParameters(locRPhi, locZ);
212 } else {
213 // Local paramters of a disk are
214 // Trk::locR = 0
215 // Trk::locPhi = 1
216 double z = surfRefPoint.z();
217 double r = z * tantheta;
220 return Trk::LocalParameters(locR, locPhi);
221 }
222}
223
224
226 const CaloDetDescrManager &caloDDMgr,
227 ROIPhiRZContainer &output_rois,
228 std::vector<uint_fast8_t> &max_output,
229 std::vector<unsigned int> &n_rois) const {
230
231 double energy = cluster.e();
232
233 // do we want to make energy be EM energy only?
234 if (m_EMEnergyOnly) {
235 static const SG::AuxElement::ConstAccessor<float> acc("EMFraction");
236 double emFrac(0.);
237 if (acc.isAvailable(cluster)) {
238 emFrac = acc(cluster);
240 emFrac)) {
241 ATH_MSG_ERROR("EM energy requested, but No EM fraction momement stored");
242 return;
243 }
244 energy *= emFrac;
245 }
246
247 std::unique_ptr<const Trk::Surface> surface( getCaloSurface(cluster, caloDDMgr) );
248 if (!surface) {
249 ATH_MSG_ERROR( "Failed to create surface for cluster");
250 return;
251 }
252
253 const Trk::LocalParameters localParams( getClusterLocalParameters(cluster, *surface) );
254
255 Amg::Vector3D global_position( surface->localToGlobal( localParams) );
256 double et = energy * std::sin(global_position.theta());
257 if ( et >= m_sortedMinPtEm[0]){
258 unsigned int roi_idx=output_rois.size();
259 output_rois.addROI(global_position, m_maxPhiWidth);
260
261 unsigned int n_duplicates = output_rois.size()-roi_idx-1;
262 if (n_duplicates>0) {
263 m_duplicateROI += n_duplicates;
264 }
265
266 unsigned int output_idx=0;
267 for ( ; output_idx<m_outputIndex.size(); ++output_idx) {
268 if (et < m_sortedMinPtEm[output_idx]) break;
269 n_rois[output_idx] += n_duplicates+1;
270 }
271 // addROI may duplicate the ROI at phi - 2 pi
272 // So, have to set the last output_idx for all newly added ROIs
273 if (max_output.size() < output_rois.size()) {
274 max_output.resize (output_rois.size());
275 }
276 for (; roi_idx < output_rois.size(); ++roi_idx) {
277 max_output[roi_idx]=output_idx;
278 }
279
280 }
281 else {
282 ATH_MSG_DEBUG("Skip selected cluster " << energy << " * " << std::sin(global_position.theta()) << " = " << energy * std::sin(global_position.theta())<< " >= " << m_sortedMinPtEm[0] );
283 }
284}
285}
#define M_PI
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
Scalar theta() const
theta method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_DEBUG(x)
static Double_t a
#define z
An algorithm that can be simultaneously executed in multiple threads.
This class provides the client interface for accessing the detector description information common to...
static Trk::LocalParameters getClusterLocalParameters(const xAOD::CaloCluster &cluster, const Trk::Surface &surf)
StatusCode execute(const EventContext &ctx) const override
SG::WriteHandleKeyArray< ROIPhiRZContainer > m_outputClusterContainerName
Name of the ROI output collection.
const Trk::Surface * getCaloSurface(const xAOD::CaloCluster &cluster, const CaloDetDescrManager &caloDDMgr) const
Gaudi::Property< std::vector< float > > m_minPtEm
CaloClusterROIPhiRZContainerMaker(const std::string &name, ISvcLocator *pSvcLocator)
ToolHandle< ICaloSurfaceBuilder > m_calosurf
Tool to build calorimeter layer surfaces.
SG::ReadHandleKey< xAOD::CaloClusterContainer > m_inputClusterContainerName
Name of the cluster intput collection.
Gaudi::Property< std::vector< float > > m_phiWidth
SG::ReadCondHandleKey< CaloDetDescrManager > m_caloMgrKey
Name of the CaloDetDescrManager condition object.
void addROI(const xAOD::CaloCluster &cluster, const CaloDetDescrManager &caloDDMgr, ROIPhiRZContainer &output_rois, std::vector< uint_fast8_t > &max_output, std::vector< unsigned int > &n_rois) const
ToolHandle< IegammaCaloClusterSelector > m_egammaCaloClusterSelector
Tool to filter the calo clusters.
container for phi sorted ROIs defined by phi, r and z.
void addROI(const Amg::Vector3D &global_position, float roi_phi_width)
SG::ConstAccessor< T, ALLOC > ConstAccessor
Definition AuxElement.h:569
const_pointer_type cptr()
virtual bool isValid() override final
Can the handle be successfully dereferenced?
Abstract Base Class for tracking surfaces.
virtual const Amg::Vector3D & globalReferencePoint() const
Returns a global reference point on the surface, for PlaneSurface, StraightLineSurface,...
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.
virtual double phi() const
The azimuthal angle ( ) of the particle.
@ ENG_FRAC_EM
Energy fraction in EM calorimeters.
int r
Definition globals.cxx:22
Eigen::Matrix< double, 3, 1 > Vector3D
Primary Vertex Finder.
@ locR
Definition ParamDefs.h:44
@ locRPhi
Definition ParamDefs.h:40
@ locZ
local cylindrical
Definition ParamDefs.h:42
@ locPhi
local polar
Definition ParamDefs.h:45
std::pair< double, ParamDefs > DefinedParameter
Typedef to of a std::pair<double, ParamDefs> to identify a passed-through double as a specific type o...
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
bool isBarrel(const xAOD::Egamma *eg)
return true if the cluster is in the barrel
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
Extra patterns decribing particle interation process.