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
6#include <GaudiKernel/StatusCode.h>
9
13
15#include "TrkSurfaces/Surface.h"
16
17#include <limits>
18#include <numbers>
19#include <cmath>
20#include <stdexcept>
21#include <algorithm>
22#include <cstdint>
23
24namespace {
25 constexpr float PI_F = std::numbers::pi_v<float>;
26}
27
28namespace InDet {
30 ISvcLocator* pSvcLocator):
31 AthReentrantAlgorithm(name, pSvcLocator)
32{
33}
34
35// ================================================================
37= default;
38
39// =================================================================
41{
43 ATH_CHECK( m_calosurf.retrieve() );
44 ATH_CHECK( m_caloMgrKey.initialize() );
45
46 if (m_outputClusterContainerName.empty()) {
47 ATH_MSG_FATAL( "No OutputROIContainerName given.");
48 return StatusCode::FAILURE;
49 }
50 if (m_outputClusterContainerName.size() > std::numeric_limits<uint8_t>::max()) {
51 ATH_MSG_FATAL( "Too many OutputROIContainerNames given.");
52 return StatusCode::FAILURE;
53 }
54 if (m_minPtEm.size() != m_phiWidth.size() || m_minPtEm.size() != m_outputClusterContainerName.size() ) {
55 ATH_MSG_FATAL( "Number of entries in minPt, phiWidth must match number of entries in OutputROIContainerName.");
56 return StatusCode::FAILURE;
57 }
58 m_outputIndex.reserve(m_minPtEm.size());
60 for (unsigned int idx=0; idx<m_minPtEm.size(); ++idx) {
61 m_outputIndex.push_back(idx);
63 }
64 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];});
65 m_sortedMinPtEm.reserve( m_outputIndex.size());
66 for (unsigned int idx : m_outputIndex) {
67 m_sortedMinPtEm.push_back( m_minPtEm[idx] );
68 }
69
72
75
76 m_outputSorted.reserve( m_outputIndex.size() );
77 m_outputUnsorted.reserve( m_outputIndex.size() );
78 for (unsigned int output_i=0; output_i<m_outputIndex.size(); ++output_i) {
79 if (m_phiWidth[m_outputIndex[output_i]]>0.) {
80 m_outputSorted.push_back(output_i);
81 }
82 else {
83 m_outputUnsorted.push_back(output_i);
84 }
85 ATH_MSG_DEBUG( "ROIPhiRZ container " << m_outputClusterContainerName[ m_outputIndex[output_i] ]
86 << " : " << m_minPtEm[m_outputIndex[output_i] ] << " MeV " << ( m_phiWidth[m_outputIndex[output_i]]>0. ? " order by phi " : " unordered" ) );
87 }
88 return StatusCode::SUCCESS;
89}
90
91
92
93// ====================================================================
95{
96 //
97 // finalize method
98 //
99 ATH_MSG_DEBUG ("AllClusters " << m_allClusters << " selected " << m_selectedClusters << " max ROIs per event " << m_maxNROIs);
100
101 return StatusCode::SUCCESS;
102}
103
104// ======================================================================
105StatusCode CaloClusterROIPhiRZContainerMaker::execute(const EventContext& ctx) const
106{
107 if (m_inputClusterContainerNames.empty()){
108 return StatusCode::SUCCESS;
109 }
110
111 std::vector< const xAOD::CaloClusterContainer *> inputClusterContainerArr;
112 inputClusterContainerArr.reserve(m_inputClusterContainerNames.size());
113 std::size_t total_cluster_size = 0;
115 SG::ReadHandle<xAOD::CaloClusterContainer> input_container(input_container_key, ctx);
116 ATH_CHECK(input_container.isValid());
117 inputClusterContainerArr.push_back(input_container.cptr());
118 total_cluster_size += input_container->size();
119 }
120
122 ATH_CHECK(caloMgrHandle.isValid());
123 const CaloDetDescrManager *caloMgr = caloMgrHandle.cptr();
124
125 unsigned int all_clusters{};
126 unsigned int selected_clusters{};
127 ROIPhiRZContainer rois; // temporary ROI container
128 std::vector<unsigned int > n_rois; // number of ROIs per output container
129 n_rois.resize(m_outputIndex.size(),0);
130
131 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
132 rois.reserve( total_cluster_size);
133 max_output.resize(total_cluster_size);
134 // Size of rois might be larger than total_cluster_size if a ROI close to +-pi gets duplicated...
135 // so don't warn. See ATLASRECTS-7160.
136
137 // create ROIs.
138 // first they are only stored in the temporary container
139 for (const xAOD::CaloClusterContainer *container : inputClusterContainerArr)
140 {
141 for (const xAOD::CaloCluster* cluster : *container){
142 all_clusters++;
143 if (m_egammaCaloClusterSelector->passSelection(cluster,*caloMgr))
144 {
145 selected_clusters++;
146 addROI(*cluster, *caloMgr, rois, max_output, n_rois);
147 }
148 }
149 }
150
151
152 // create ROI output container
153 std::vector< SG::WriteHandle<ROIPhiRZContainer> > output_rois;
154 output_rois.reserve(m_outputIndex.size());
155 for (unsigned int output_idx : m_outputIndex) {
156 unsigned int the_size = n_rois[output_rois.size()];
157 output_rois.emplace_back( m_outputClusterContainerName[output_idx], ctx);
158 ATH_CHECK( output_rois.back().record( std::make_unique<ROIPhiRZContainer>() ) );
159 output_rois.back()->reserve( the_size);
160 }
161
162 if (!m_outputSorted.empty()) {
163 // sort ROIs by phi
164 std::vector<unsigned int> roi_order;
165 roi_order.reserve( rois.size() );
166 for (unsigned int idx=0; idx< rois.size(); ++idx) { roi_order.push_back( idx ); }
167 std::sort(roi_order.begin(),roi_order.end(),[&rois](unsigned int a, unsigned int b) { return rois[a][0] < rois[b][0]; });
168 // copy ROIs in sort order to output container which are to be sorted
169 for (unsigned int roi_i : roi_order) {
170 for (unsigned int output_i : m_outputSorted) {
171 if (output_i>=max_output[roi_i]) break;
172 output_rois[output_i]->push_back( rois[ roi_i ] );
173 }
174 }
175 }
176
177 // copy ROIs in original order to output container which should have the original order
178 // also remove duplicates
179 if (!m_outputUnsorted.empty()) {
180 for (unsigned int roi_unordered_i=0; roi_unordered_i < rois.size(); ++roi_unordered_i) {
181 for (unsigned int output_i : m_outputUnsorted) {
182 if (output_i>=max_output[roi_unordered_i]) break;
183 if (std::abs(rois[ roi_unordered_i ][0])<PI_F or (rois[ roi_unordered_i ][0] == PI_F)) {
184 output_rois[output_i]->push_back( rois[ roi_unordered_i ] );
185 }
186 }
187 }
188 }
189
190 // gather statistics
191 {
192 unsigned int max_size;
193 do {
194 max_size = m_maxNROIs;
195 } while (rois.size()>max_size && ! m_maxNROIs.compare_exchange_weak(max_size, rois.size()));
196 }
197 m_allClusters += all_clusters;
198 m_selectedClusters += selected_clusters;
199 return StatusCode::SUCCESS;
200}
201
203 const Trk::Surface &surf)
204{
205
206 Amg::Vector3D surfRefPoint = surf.globalReferencePoint();
207
208 double eta = cluster.eta();
209 double theta = 2 * atan(exp(-eta)); // -log(tan(theta/2));
210 double tantheta = tan(theta);
211 double phi = cluster.phi();
212
213 if (xAOD::EgammaHelpers::isBarrel(&cluster)) {
214 // Two corindate in a cyclinder are
215 // Trk::locRPhi = 0 (ie phi)
216 // Trk::locZ = 1(ie z)
217 double r = surfRefPoint.perp();
218 double z = tantheta == 0 ? 0. : r / tantheta;
221 return Trk::LocalParameters(locRPhi, locZ);
222 } else {
223 // Local paramters of a disk are
224 // Trk::locR = 0
225 // Trk::locPhi = 1
226 double z = surfRefPoint.z();
227 double r = z * tantheta;
230 return Trk::LocalParameters(locR, locPhi);
231 }
232}
233
234
236 const CaloDetDescrManager &caloDDMgr,
237 ROIPhiRZContainer &output_rois,
238 std::vector<uint_fast8_t> &max_output,
239 std::vector<unsigned int> &n_rois) const {
240
241 double energy = cluster.e();
242
243 // do we want to make energy be EM energy only?
244 if (m_EMEnergyOnly) {
245 static const SG::AuxElement::ConstAccessor<float> acc("EMFraction");
246 double emFrac(0.);
247 if (acc.isAvailable(cluster)) {
248 emFrac = acc(cluster);
250 emFrac)) {
251 ATH_MSG_ERROR("EM energy requested, but No EM fraction momement stored");
252 return;
253 }
254 energy *= emFrac;
255 }
256
257 std::unique_ptr<const Trk::Surface> surface( getCaloSurface(cluster, caloDDMgr) );
258 if (!surface) {
259 ATH_MSG_ERROR( "Failed to create surface for cluster");
260 return;
261 }
262
263 const Trk::LocalParameters localParams( getClusterLocalParameters(cluster, *surface) );
264
265 Amg::Vector3D global_position( surface->localToGlobal( localParams) );
266 double et = energy * std::sin(global_position.theta());
267 if ( et >= m_sortedMinPtEm[0]){
268 unsigned int roi_idx=output_rois.size();
269 output_rois.addROI(global_position, m_maxPhiWidth);
270
271 unsigned int n_duplicates = output_rois.size()-roi_idx-1;
272 if (n_duplicates>0) {
273 m_duplicateROI += n_duplicates;
274 }
275
276 unsigned int output_idx=0;
277 for ( ; output_idx<m_outputIndex.size(); ++output_idx) {
278 if (et < m_sortedMinPtEm[output_idx]) break;
279 n_rois[output_idx] += n_duplicates+1;
280 }
281 // addROI may duplicate the ROI at phi - 2 pi
282 // So, have to set the last output_idx for all newly added ROIs
283 if (max_output.size() < output_rois.size()) {
284 max_output.resize (output_rois.size());
285 }
286 for (; roi_idx < output_rois.size(); ++roi_idx) {
287 max_output[roi_idx]=output_idx;
288 }
289
290 }
291 else {
292 ATH_MSG_DEBUG("Skip selected cluster " << energy << " * " << std::sin(global_position.theta()) << " = " << energy * std::sin(global_position.theta())<< " >= " << m_sortedMinPtEm[0] );
293 }
294}
295}
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
Handle class for reading from StoreGate.
#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
SG::ReadHandleKeyArray< xAOD::CaloClusterContainer > m_inputClusterContainerNames
Names of the cluster intput collections.
CaloClusterROIPhiRZContainerMaker(const std::string &name, ISvcLocator *pSvcLocator)
ToolHandle< ICaloSurfaceBuilder > m_calosurf
Tool to build calorimeter layer surfaces.
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)
const_pointer_type cptr()
Property holding a SG store/key/clid from which a ReadHandle is made.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
const_pointer_type cptr()
Dereference the pointer.
Abstract Base Class for tracking surfaces.
Definition Surface.h:79
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.
CaloClusterContainer_v1 CaloClusterContainer
Define the latest version of the calorimeter cluster container.
Extra patterns decribing particle interation process.