40#include <CLHEP/Vector/LorentzVector.h>
48using CLHEP::HepLorentzVector;
54constexpr std::array<std::pair<std::string_view, xAOD::CaloCluster::MomentType>, 19>
77constexpr std::array<std::string_view, 19> s_aodMomentNames{{
86 "ENG_CALIB_DEAD_EMB0",
87 "ENG_CALIB_DEAD_TILE0",
88 "ENG_CALIB_DEAD_TILEG3",
89 "ENG_CALIB_DEAD_EME0",
90 "ENG_CALIB_DEAD_HEC0",
91 "ENG_CALIB_DEAD_FCAL",
92 "ENG_CALIB_DEAD_LEAKAGE",
93 "ENG_CALIB_DEAD_UNCLASS",
105 const std::string& name,
106 const IInterface* parent)
118 declareInterface<CaloClusterCollectionProcessor>(
this);
122 for (
const auto& [thisName, moment] : s_validMomentNames) {
128 for (
const std::string_view thisName : s_aodMomentNames) {
144 for (
int im = 0; im < 3; im++) {
171 if (name == vname.first) {
179 msg() << MSG::ERROR <<
"Moment " << name
180 <<
" is not a valid Moment name and will be ignored! "
181 <<
"Valid names are:";
182 for (
unsigned int i = 0; i <
m_validNames.size(); i++) {
193 switch (vname.second) {
221 ATH_MSG_INFO(
"Usage of ParticleID was switched off (UseParticleID==False), no ENG_CALIB_FRAC_* moments will be available");
227 if (vname.first == name) {
256 return StatusCode::SUCCESS;
265 const double (&rmaxOut)[3],
266 std::array<std::vector<std::vector<CalibHitIPhiIEtaRange>>, 3>& i_phi_eta)
268 for (
int im = 0; im < 3; ++im) {
269 i_phi_eta[im].clear();
270 i_phi_eta[im].resize(n_eta_out);
273 for (
int jeta = 0; jeta < n_eta_out; ++jeta) {
274 const double eta0 = (jeta + 0.5) * out_eta_max / n_eta_out;
275 HepLorentzVector middle(1, 0, 0, 1);
276 middle.setREtaPhi(1. / std::cosh(eta0), eta0, 0.0);
279 for (
int im = 0; im < 3; ++im) {
283 for (
int jp = -n_phi_out; jp < n_phi_out; ++jp) {
284 const double phi = (jp + 0.5) * out_phi_max / n_phi_out;
285 int ietaMin[3] = {n_eta_out, n_eta_out, n_eta_out};
286 int ietaMax[3] = {-n_eta_out, -n_eta_out, -n_eta_out};
288 for (
int je = -n_eta_out; je < n_eta_out; ++je) {
289 const double eta = (je + 0.5) * out_eta_max / n_eta_out;
290 HepLorentzVector cpoint(1, 0, 0, 1);
291 cpoint.setREtaPhi(1. / std::cosh(
eta),
eta,
phi);
292 const double r = middle.angle(cpoint.vect());
293 for (
int im = 0; im < 3; ++im) {
294 if (
r < x_rmaxOut[im]) {
295 if (je < ietaMin[im]) {
298 if (je > ietaMax[im]) {
305 for (
int im = 0; im < 3; ++im) {
306 if (ietaMin[im] <= ietaMax[im]) {
308 theRange.
iPhi =
static_cast<char>(jp);
309 theRange.
iEtaMin =
static_cast<char>(ietaMin[im]);
310 theRange.
iEtaMax =
static_cast<char>(ietaMax[im]);
311 i_phi_eta[im][jeta].push_back(theRange);
330 for (; cellIter != cellIterEnd; ++cellIter) {
335 CellInfoSet_t::iterator bookmark = cellInfo.lower_bound(myId);
336 if (bookmark == cellInfo.end() || bookmark->first != myId) {
337 if (bookmark != cellInfo.begin()) {
340 cellInfo.emplace_hint(bookmark, myId, std::move(info));
343 bookmark->second.Add(info);
361 const std::array<std::vector<std::vector<CalibHitIPhiIEtaRange>>, 3>& i_phi_eta,
362 const std::array<bool, 3>& doOutOfCluster,
363 const std::array<ClusList*, 3>& clusLists)
365 for (
unsigned int ii = 0; ii < 3; ++ii) {
366 ClusList* pClusList = clusLists[ii];
367 if (!doOutOfCluster[ii] || pClusList ==
nullptr) {
374 const MyClusInfo& clusInfo = clusInfoVec[iClus];
381 if (theCluster->eta() < 0.) {
385 const int jeta =
static_cast<int>(std::floor(n_eta_out * (theCluster->eta() / out_eta_max)));
386 int jphi =
static_cast<int>(std::floor(n_phi_out * (theCluster->phi() / out_phi_max)));
388 if (jeta < -n_eta_out || jeta >= n_eta_out) {
392 if (jphi < -n_phi_out) {
393 jphi += 2 * n_phi_out;
395 if (jphi >= n_phi_out) {
396 jphi -= 2 * n_phi_out;
399 unsigned int iEtaBin =
static_cast<unsigned int>(jeta);
401 iEtaBin = std::abs(jeta) - 1;
404 const std::vector<CalibHitIPhiIEtaRange>&
bins = i_phi_eta[ii][iEtaBin];
406 int jp = range.iPhi + jphi;
407 if (jp < -n_phi_out) {
410 if (jp >= n_phi_out) {
414 const int jEtaMin = (iEtaSign < 0) ? -range.iEtaMax - 1 : range.iEtaMin;
415 const int jEtaMax = (iEtaSign < 0) ? -range.iEtaMin - 1 : range.iEtaMax;
417 for (
int je = jEtaMin; je <= jEtaMax; ++je) {
418 (*pClusList)[(jp + n_phi_out) * (2 * n_eta_out + 1) + je + n_eta_out].push_back(iClus);
433 ATH_MSG_DEBUG(
"Starting CaloCalibClusterMomentsMaker2::execute");
437 bool foundAllContainers (
true);
438 std::vector<const CaloCalibrationHitContainer *> v_cchc;
447 msg(MSG::ERROR) <<
"SG does not contain calibration hit container "
450 foundAllContainers =
false;
453 v_cchc.push_back(cchc.
cptr());
457 std::vector<const CaloCalibrationHitContainer *> v_dmcchc;
466 ATH_MSG_ERROR(
"SG does not contain DM calibration hit container "
469 foundAllContainers =
false;
472 v_dmcchc.push_back(cchc.
cptr());
480 if ( !foundAllContainers ) {
481 return StatusCode::SUCCESS;
497 unsigned int nHitsTotal = 0;
498 unsigned int nHitsWithoutParticleUID = 0;
506 nHitsWithoutParticleUID,
509 ATH_MSG_ERROR(
"Invalid uniqueID detected - this sample cannot be properly analysed.");
517 ATH_MSG_INFO(
"Calibration hits do not have ParticleUID, ids of particle-caused hits are always 0. Continuing without ParticleID machinery.");
518 useParticleID =
false;
525 if (doCalibFrac && !truthParticleContainerReadHandle.
isValid()) {
526 ATH_MSG_WARNING(
"Invalid read handle to TruthParticleContainer with key: "
531 std::array<std::vector<double>, 3> engCalibOut;
536 std::array<ClusList, 3> clusLists;
537 const std::array<bool, 3> doOutOfCluster{{
540 const std::array<bool, 3> doClusterLists{{
549 for (
unsigned int ii = 0; ii < 3; ++ii) {
550 if (doClusterLists[ii]) {
552 engCalibOut[ii].resize(theClusColl->
size(), 0.0);
556 std::array<ClusList*, 3> clusListPtrs{{&clusLists[0], &clusLists[1], &clusLists[2]}};
572 std::array<const ClusList*, 3> constClusListPtrs{{
573 &clusLists[0], &clusLists[1], &clusLists[2]
586 [&engCalibOut](
unsigned int ii,
int iClus,
int ,
double energy) {
587 engCalibOut[ii][iClus] += energy;
598 pClusList = &clusLists[0];
600 pClusList = &clusLists[1];
602 pClusList = &clusLists[2];
612 [&clusInfoVec](
int iClus,
int ,
int nDmArea,
double energy) {
613 clusInfoVec[iClus].engCalibDeadInArea[nDmArea] += energy;
619 std::vector<double> engCalibFrac;
622 std::map<unsigned int, int> truthIDToPdgCodeMap;
625 for (
const auto *thisTruthParticle : *truthParticleContainerReadHandle ) {
627 if (!thisTruthParticle) {
632 truthIDToPdgCodeMap[
HepMC::uniqueID(thisTruthParticle)] = thisTruthParticle->pdgId();
637 for (clusIter = theClusColl->
begin(), iClus = 0;
638 clusIter != clusIterEnd;
639 ++clusIter, ++iClus) {
669 double eng_calib_dead_unclass = eng_calib_dead_tot - eng_calib_dead_emb0 - eng_calib_dead_tile0
670 - eng_calib_dead_tileg3 - eng_calib_dead_eme0 - eng_calib_dead_hec0 - eng_calib_dead_fcal
671 - eng_calib_dead_leakage;
682 if (
auto it = truthIDToPdgCodeMap.find(p.first); it != truthIDToPdgCodeMap.end()) {
685 ATH_MSG_WARNING(
"truthIDToPdgCodeMap cannot find an entry with uniqueID " << p.first);
688 if (std::abs(pdg_id) == 211) {
690 }
else if (pdg_id == 111 || pdg_id == 22 || std::abs(pdg_id) == 11) {
696 for (
size_t i = 0; i < engCalibFrac.size(); i++) {
705 moment_name_set::const_iterator vMomentsIter =
m_validMoments.begin();
706 moment_name_set::const_iterator vMomentsIterEnd =
m_validMoments.end();
709 for (; vMomentsIter != vMomentsIterEnd; ++vMomentsIter, ++iMoment) {
711 switch (vMomentsIter->second) {
717 myMoments[iMoment] = engCalibOut[0][iClus];
720 myMoments[iMoment] = engCalibOut[1][iClus];
723 myMoments[iMoment] = engCalibOut[2][iClus];
735 myMoments[iMoment] = eng_calib_dead_tot;
738 myMoments[iMoment] = eng_calib_dead_emb0;
741 myMoments[iMoment] = eng_calib_dead_tile0;
744 myMoments[iMoment] = eng_calib_dead_tileg3;
747 myMoments[iMoment] = eng_calib_dead_eme0;
750 myMoments[iMoment] = eng_calib_dead_hec0;
753 myMoments[iMoment] = eng_calib_dead_fcal;
756 myMoments[iMoment] = eng_calib_dead_leakage;
759 myMoments[iMoment] = eng_calib_dead_unclass;
775 theCluster->
insertMoment(vMomentsIter->second, myMoments[iMoment]);
780 return StatusCode::SUCCESS;
789 double eta = fabs(
x);
792 ff = atan(5.0 * 1.7 / (200.0 * cosh(
eta)));
793 }
else if (
eta < 3.2) {
794 ff = atan(5.0 * 1.6 / (420. / tanh(
eta)));
796 ff = atan(5.0 * 0.95 / (505. / tanh(
eta)));
798 return ff * (1. / atan(5.0 * 1.7 / 200.0));
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
#define ATH_CHECK
Evaluate an expression and check for errors.
bool isValid() const
Test to see if the link can be dereferenced.
#define ATH_MSG_WARNING(x)
Definition of CaloDetDescrManager.
static const std::vector< std::string > bins
Handle class for reading from StoreGate.
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
const ServiceHandle< StoreGateSvc > & detStore() const
std::array< double, CaloSampling::Unknown+1 > engSmp
ClusCalibEnergy engCalibIn
std::map< int, ClusCalibEnergy > engCalibParticle
std::array< double, CaloDmDescrArea::DMA_MAX > engCalibDeadInArea
const CaloDM_ID * m_caloDM_ID
virtual StatusCode initialize() override
void accumulateDeadMaterialEnergy(const std::vector< const CaloCalibrationHitContainer * > &v_dmcchc, const xAOD::CaloClusterContainer &theClusColl, const ClusInfo_t &clusInfoVec, const ClusList &clusList, bool useParticleID, AddDeadMaterialEnergy &&addDeadMaterialEnergy) const
Accumulate dead-material calibration-hit energy assigned to clusters.
std::vector< MyClusInfo > ClusInfo_t
SG::ReadHandleKeyArray< CaloCalibrationHitContainer > m_DMCalibrationHitContainerNames
moment_name_vector m_validNames
std::set< xAOD::CaloCluster::MomentType > m_momentsAOD
virtual StatusCode execute(const EventContext &ctx, xAOD::CaloClusterContainer *theClusColl) const override
Execute on an entire collection of clusters.
moment_name_set m_validMoments
static void initializeOutOfClusterDistanceTables(int n_phi_out, int n_eta_out, double out_phi_max, double out_eta_max, const double(&rmaxOut)[3], std::array< std::vector< std::vector< CalibHitIPhiIEtaRange > >, 3 > &i_phi_eta)
Precompute eta/phi lookup tables for quick out-of-cluster hit association to clusters.
SG::ReadHandleKeyArray< CaloCalibrationHitContainer > m_CalibrationHitContainerNames
const CaloCell_ID * m_calo_id
bool m_doDeadEnergySharing
std::map< Identifier, MyCellInfo > CellInfoSet_t
static void accumulateClusterCalibHits(const std::vector< const CaloCalibrationHitContainer * > &v_cchc, const CellInfoSet_t &cellInfo, const CaloCell_ID &calo_id, ClusInfo_t &clusInfoVec, unsigned int &nHitsTotal, unsigned int &nHitsWithoutParticleUID, bool useParticleID, InvalidUniqueIdHandler &&invalidUniqueIdHandler)
Accumulate calibration-hit energy inside clusters.
SG::ReadHandleKey< xAOD::TruthParticleContainer > m_truthParticleContainerKey
std::atomic< bool > m_foundAllContainers
std::vector< std::string > m_momentsNames
static void buildOutOfClusterClusterLists(const xAOD::CaloClusterContainer &theClusColl, const ClusInfo_t &clusInfoVec, int n_phi_out, int n_eta_out, double out_phi_max, double out_eta_max, const std::array< std::vector< std::vector< CalibHitIPhiIEtaRange > >, 3 > &i_phi_eta, const std::array< bool, 3 > &doOutOfCluster, const std::array< ClusList *, 3 > &clusLists)
Build lookup lists of clusters for out-of-cluster energy sharing.
static void buildCellInfoMap(const xAOD::CaloClusterContainer &theClusColl, CellInfoSet_t &cellInfo)
Build a map of calorimeter cells contributing to clusters.
SG::ReadCondHandleKey< CaloDetDescrManager > m_caloDetDescrMgrKey
CaloCalibClusterMomentsMaker2(const std::string &type, const std::string &name, const IInterface *parent)
std::array< std::vector< std::vector< CalibHitIPhiIEtaRange > >, 3 > m_i_phi_eta
static double angle_mollier_factor(double x)
const CaloDmDescrManager * m_caloDmDescrManager
std::vector< std::string > m_momentsNamesAOD
std::vector< std::vector< int > > ClusList
static void accumulateOutOfClusterEnergy(const std::vector< const CaloCalibrationHitContainer * > &v_cchc, const CellInfoSet_t &cellInfo, const CaloDetDescrManager &calo_dd_man, const ClusInfo_t &clusInfoVec, int n_phi_out, int n_eta_out, double out_phi_max, double out_eta_max, const std::array< bool, 3 > &doOutOfCluster, const std::array< const ClusList *, 3 > &clusLists, AddOutOfClusterEnergy &&addOutOfClusterEnergy)
std::pair< std::string, xAOD::CaloCluster::MomentType > moment_name_pair
Data object for each calorimeter readout cell.
Identifier ID() const
get ID (from cached data member) non-virtual and inline for fast access
weight_t weight() const
Accessor for weight associated to this cell.
This class provides the client interface for accessing the detector description information common to...
static const CaloDmDescrManager * instance()
DataModel_detail::iterator< DataVector > iterator
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
size_type size() const noexcept
Returns the number of elements in the collection.
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.
void insertMoment(MomentType type, double value)
CaloClusterCellLink::const_iterator const_cell_iterator
Iterator of the underlying CaloClusterCellLink (explicitly const version).
@ ENG_CALIB_OUT_M
Attached Calibration Hit energy outside clusters but inside the calorimeter with medium matching (Ang...
@ ENG_CALIB_OUT_L
Attached Calibration Hit energy outside clusters but inside the calorimeter with loose matching (Angl...
@ 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.
@ ENG_CALIB_FRAC_REST
Calibration Hit energy inside the cluster caused by other particles.
@ 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_OUT_T
Attached Calibration Hit energy outside clusters but inside the calorimeter with tight matching (Angl...
@ ENG_CALIB_DEAD_LEAKAGE
Attached Calibration Hit energy in dead material behind calorimeters.
@ ENG_CALIB_FRAC_HAD
Calibration Hit energy inside the cluster caused by charged pi+ and pi-.
@ 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.
@ ENG_CALIB_DEAD_TOT
Attached Calibration Hit energy in dead material.
@ ENG_CALIB_TILEG3
Calibration Hit energy inside the cluster scintillator.
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
CaloClusterContainer_v1 CaloClusterContainer
Define the latest version of the calorimeter cluster container.