42#include <CLHEP/Vector/LorentzVector.h>
46using CLHEP::HepLorentzVector;
54 const std::string& name,
55 const IInterface* parent)
58 declareInterface<CaloClusterCollectionProcessor>(
this);
59 for (
int im = 0; im < 3; im++) {
74 if (name == vname.first) {
82 msg() << MSG::ERROR <<
"Moment " << name
83 <<
" is not a valid Moment name and will be ignored! "
84 <<
"Valid names are:";
96 switch (vname.second) {
124 ATH_MSG_INFO(
"Usage of ParticleID was switched off (UseParticleID==False), no ENG_CALIB_FRAC_* moments will be available");
130 if (vname.first == name) {
159 return StatusCode::SUCCESS;
168 const double (&rmaxOut)[3],
169 std::array<std::vector<std::vector<CalibHitIPhiIEtaRange>>, 3>& i_phi_eta)
171 for (
int im = 0; im < 3; ++im) {
172 i_phi_eta[im].clear();
173 i_phi_eta[im].resize(n_eta_out);
176 for (
int jeta = 0; jeta < n_eta_out; ++jeta) {
177 const double eta0 = (jeta + 0.5) * out_eta_max / n_eta_out;
178 HepLorentzVector middle(1, 0, 0, 1);
179 middle.setREtaPhi(1. / std::cosh(eta0), eta0, 0.0);
182 for (
int im = 0; im < 3; ++im) {
186 for (
int jp = -n_phi_out; jp < n_phi_out; ++jp) {
187 const double phi = (jp + 0.5) * out_phi_max / n_phi_out;
188 int ietaMin[3] = {n_eta_out, n_eta_out, n_eta_out};
189 int ietaMax[3] = {-n_eta_out, -n_eta_out, -n_eta_out};
191 for (
int je = -n_eta_out; je < n_eta_out; ++je) {
192 const double eta = (je + 0.5) * out_eta_max / n_eta_out;
193 HepLorentzVector cpoint(1, 0, 0, 1);
194 cpoint.setREtaPhi(1. / std::cosh(
eta),
eta,
phi);
195 const double r = middle.angle(cpoint.vect());
196 for (
int im = 0; im < 3; ++im) {
197 if (
r < x_rmaxOut[im]) {
198 if (je < ietaMin[im]) {
201 if (je > ietaMax[im]) {
208 for (
int im = 0; im < 3; ++im) {
209 if (ietaMin[im] <= ietaMax[im]) {
211 theRange.
iPhi =
static_cast<char>(jp);
212 theRange.
iEtaMin =
static_cast<char>(ietaMin[im]);
213 theRange.
iEtaMax =
static_cast<char>(ietaMax[im]);
214 i_phi_eta[im][jeta].push_back(theRange);
233 for (; cellIter != cellIterEnd; ++cellIter) {
238 CellInfoSet_t::iterator bookmark = cellInfo.lower_bound(myId);
239 if (bookmark == cellInfo.end() || bookmark->first != myId) {
240 if (bookmark != cellInfo.begin()) {
243 cellInfo.emplace_hint(bookmark, myId, std::move(info));
246 bookmark->second.Add(info);
264 const std::array<std::vector<std::vector<CalibHitIPhiIEtaRange>>, 3>& i_phi_eta,
265 const std::array<bool, 3>& doOutOfCluster,
266 const std::array<ClusList*, 3>& clusLists)
268 for (
unsigned int ii = 0; ii < 3; ++ii) {
269 ClusList* pClusList = clusLists[ii];
270 if (!doOutOfCluster[ii] || pClusList ==
nullptr) {
277 const MyClusInfo& clusInfo = clusInfoVec[iClus];
284 if (theCluster->eta() < 0.) {
288 const int jeta =
static_cast<int>(std::floor(n_eta_out * (theCluster->eta() / out_eta_max)));
289 int jphi =
static_cast<int>(std::floor(n_phi_out * (theCluster->phi() / out_phi_max)));
291 if (jeta < -n_eta_out || jeta >= n_eta_out) {
295 if (jphi < -n_phi_out) {
296 jphi += 2 * n_phi_out;
298 if (jphi >= n_phi_out) {
299 jphi -= 2 * n_phi_out;
302 unsigned int iEtaBin =
static_cast<unsigned int>(jeta);
304 iEtaBin = std::abs(jeta) - 1;
307 const std::vector<CalibHitIPhiIEtaRange>&
bins = i_phi_eta[ii][iEtaBin];
309 int jp = range.iPhi + jphi;
310 if (jp < -n_phi_out) {
313 if (jp >= n_phi_out) {
317 const int jEtaMin = (iEtaSign < 0) ? -range.iEtaMax - 1 : range.iEtaMin;
318 const int jEtaMax = (iEtaSign < 0) ? -range.iEtaMin - 1 : range.iEtaMax;
320 for (
int je = jEtaMin; je <= jEtaMax; ++je) {
321 (*pClusList)[(jp + n_phi_out) * (2 * n_eta_out + 1) + je + n_eta_out].push_back(iClus);
336 ATH_MSG_DEBUG(
"Starting CaloCalibClusterMomentsMaker2::execute");
340 bool foundAllContainers (
true);
341 std::vector<const CaloCalibrationHitContainer *> v_cchc;
350 msg(MSG::ERROR) <<
"SG does not contain calibration hit container "
353 foundAllContainers =
false;
356 v_cchc.push_back(cchc.
cptr());
360 std::vector<const CaloCalibrationHitContainer *> v_dmcchc;
369 ATH_MSG_ERROR(
"SG does not contain DM calibration hit container "
372 foundAllContainers =
false;
375 v_dmcchc.push_back(cchc.
cptr());
383 if ( !foundAllContainers ) {
384 return StatusCode::SUCCESS;
400 unsigned int nHitsTotal = 0;
401 unsigned int nHitsWithoutParticleUID = 0;
409 nHitsWithoutParticleUID,
412 ATH_MSG_ERROR(
"Invalid uniqueID detected - this sample cannot be properly analysed.");
420 ATH_MSG_INFO(
"Calibration hits do not have ParticleUID, ids of particle-caused hits are always 0. Continuing without ParticleID machinery.");
421 useParticleID =
false;
428 if (doCalibFrac && !truthParticleContainerReadHandle.
isValid()) {
429 ATH_MSG_WARNING(
"Invalid read handle to TruthParticleContainer with key: "
434 std::array<std::vector<double>, 3> engCalibOut;
439 std::array<ClusList, 3> clusLists;
440 const std::array<bool, 3> doOutOfCluster{{
443 const std::array<bool, 3> doClusterLists{{
452 for (
unsigned int ii = 0; ii < 3; ++ii) {
453 if (doClusterLists[ii]) {
455 engCalibOut[ii].resize(theClusColl->
size(), 0.0);
459 std::array<ClusList*, 3> clusListPtrs{{&clusLists[0], &clusLists[1], &clusLists[2]}};
475 std::array<const ClusList*, 3> constClusListPtrs{{
476 &clusLists[0], &clusLists[1], &clusLists[2]
489 [&engCalibOut](
unsigned int ii,
int iClus,
int ,
double energy) {
490 engCalibOut[ii][iClus] += energy;
501 pClusList = &clusLists[0];
503 pClusList = &clusLists[1];
505 pClusList = &clusLists[2];
537 int hitClusVecIndex = 0;
538 std::vector<int> hitClusIndex(theClusColl->
size());
539 std::vector<double> hitClusEffEnergy(theClusColl->
size());
540 double hitClusNorm = 0.0;
543 for (
unsigned int i_cls = 0;
552 double engClusTruthUniqueIDCalib = pos->second.engTot;
555 double sum_smp_energy = 0.0;
562 sum_smp_energy += pos->second.engSmp[nsmp];
565 if (sum_smp_energy > 0.0) {
566 double phi_diff = myCDDE->
phi() - theCluster->
phi();
567 if (phi_diff <= -
M_PI) {
568 phi_diff += 2. *
M_PI;
569 }
else if (phi_diff >
M_PI) {
570 phi_diff -= 2. *
M_PI;
572 double eta_diff = (myCDDE->
eta() - theCluster->
eta());
573 float distance = sqrt(eta_diff * eta_diff + phi_diff * phi_diff);
577 hitClusIndex[hitClusVecIndex] = iClus;
578 hitClusEffEnergy[hitClusVecIndex++] = effEner;
579 hitClusNorm += effEner;
585 hitClusIndex.resize(hitClusVecIndex);
586 hitClusEffEnergy.resize(hitClusVecIndex);
589 if (hitClusNorm > 0.0) {
590 const double inv_hitClusNorm = 1. / hitClusNorm;
591 for (
unsigned int i_cls = 0; i_cls < hitClusIndex.size(); i_cls++) {
592 int iClus = hitClusIndex[i_cls];
593 double dm_weight = hitClusEffEnergy[i_cls] * inv_hitClusNorm;
594 if (dm_weight > 1.0 || dm_weight < 0.0) {
595 std::cout <<
"CaloCalibClusterMomentsMaker2::execute() ->Error! Strange weight "
596 << dm_weight << std::endl;
597 std::cout << hitClusEffEnergy[i_cls] <<
" " << hitClusNorm << std::endl;
599 clusInfoVec[iClus].engCalibDeadInArea[nDmArea] += hit->energyTotal() * dm_weight;
613 std::vector<double> engCalibFrac;
616 std::map<unsigned int, int> truthIDToPdgCodeMap;
619 for (
const auto *thisTruthParticle : *truthParticleContainerReadHandle ) {
621 if (!thisTruthParticle) {
626 truthIDToPdgCodeMap[
HepMC::uniqueID(thisTruthParticle)] = thisTruthParticle->pdgId();
631 for (clusIter = theClusColl->
begin(), iClus = 0;
632 clusIter != clusIterEnd;
633 ++clusIter, ++iClus) {
663 double eng_calib_dead_unclass = eng_calib_dead_tot - eng_calib_dead_emb0 - eng_calib_dead_tile0
664 - eng_calib_dead_tileg3 - eng_calib_dead_eme0 - eng_calib_dead_hec0 - eng_calib_dead_fcal
665 - eng_calib_dead_leakage;
676 if (
auto it = truthIDToPdgCodeMap.find(p.first); it != truthIDToPdgCodeMap.end()) {
679 ATH_MSG_WARNING(
"truthIDToPdgCodeMap cannot find an entry with uniqueID " << p.first);
682 if (std::abs(pdg_id) == 211) {
684 }
else if (pdg_id == 111 || pdg_id == 22 || std::abs(pdg_id) == 11) {
690 for (
size_t i = 0; i < engCalibFrac.size(); i++) {
699 moment_name_set::const_iterator vMomentsIter =
m_validMoments.begin();
700 moment_name_set::const_iterator vMomentsIterEnd =
m_validMoments.end();
703 for (; vMomentsIter != vMomentsIterEnd; ++vMomentsIter, ++iMoment) {
705 switch (vMomentsIter->second) {
711 myMoments[iMoment] = engCalibOut[0][iClus];
714 myMoments[iMoment] = engCalibOut[1][iClus];
717 myMoments[iMoment] = engCalibOut[2][iClus];
729 myMoments[iMoment] = eng_calib_dead_tot;
732 myMoments[iMoment] = eng_calib_dead_emb0;
735 myMoments[iMoment] = eng_calib_dead_tile0;
738 myMoments[iMoment] = eng_calib_dead_tileg3;
741 myMoments[iMoment] = eng_calib_dead_eme0;
744 myMoments[iMoment] = eng_calib_dead_hec0;
747 myMoments[iMoment] = eng_calib_dead_fcal;
750 myMoments[iMoment] = eng_calib_dead_leakage;
753 myMoments[iMoment] = eng_calib_dead_unclass;
769 theCluster->
insertMoment(vMomentsIter->second, myMoments[iMoment]);
774 return StatusCode::SUCCESS;
783 double eta = fabs(
x);
786 ff = atan(5.0 * 1.7 / (200.0 * cosh(
eta)));
787 }
else if (
eta < 3.2) {
788 ff = atan(5.0 * 1.6 / (420. / tanh(
eta)));
790 ff = atan(5.0 * 0.95 / (505. / tanh(
eta)));
792 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.
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
std::vector< MyClusInfo > ClusInfo_t
SG::ReadHandleKeyArray< CaloCalibrationHitContainer > m_DMCalibrationHitContainerNames
moment_name_vector m_validNames
std::set< xAOD::CaloCluster::MomentType > m_momentsAOD
Gaudi::Property< bool > m_useParticleID
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.
Gaudi::Property< std::vector< std::string > > m_momentsNames
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
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
Gaudi::Property< int > m_MatchDmType
static double angle_mollier_factor(double x)
const CaloDmDescrManager * m_caloDmDescrManager
std::vector< std::vector< int > > ClusList
Gaudi::Property< std::vector< std::string > > m_momentsNamesAOD
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
Class to store calorimeter calibration hit.
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()
std::vector< short > m_CaloSampleNeighbours
std::vector< float > m_CaloSampleEtaMin
std::vector< float > m_CaloSampleEtaMax
const T * at(size_type n) const
Access an element, as an rvalue.
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.
virtual double eta() const
The pseudorapidity ( ) of the particle.
virtual double e() const
The total energy of the particle.
void insertMoment(MomentType type, double value)
CaloClusterCellLink::const_iterator const_cell_iterator
Iterator of the underlying CaloClusterCellLink (explicitly const version).
virtual double phi() const
The azimuthal angle ( ) of the particle.
@ 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.
constexpr int UNDEFINED_ID
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
CaloClusterContainer_v1 CaloClusterContainer
Define the latest version of the calorimeter cluster container.