ATLAS Offline Software
Loading...
Searching...
No Matches
GTowerRhoSubtractionAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
8#include <memory>
12#include "TH1F.h"
13#include "GaudiKernel/SystemOfUnits.h"
14#include "GTowerHelpers.h"
16#include <algorithm>
17
18namespace
19{
20 const static SG::AuxElement::ConstAccessor<float> accArea("area");
21 const static SG::AuxElement::Decorator<std::vector<float>> decRho("FPGARhos");
22} // namespace
23
24namespace LVL1
25{
26 GTowerRhoSubtractionAlg::GTowerRhoSubtractionAlg(const std::string &name, ISvcLocator *pSvcLocator)
27 : AthReentrantAlgorithm(name, pSvcLocator)
28 {
29 declareProperty("InputTowers", m_inputKey = "GCaloTower");
30 declareProperty("OutputTowers", m_outputKey = "GCaloTowerRhoSubtracted");
31 declareProperty("OutputRho", m_outputRhoKey = "GFEXRho");
32 declareProperty("UseNegativeTowers", m_useNegativeTowers = true);
33 declareProperty("MaxTowerEt", m_maxTowerEt = 10 * Gaudi::Units::GeV);
34 declareProperty("ForcePositiveRho", m_forcePosRho = false);
35 }
36
38
40 {
41 ATH_CHECK(m_inputKey.initialize());
42 ATH_CHECK(m_outputKey.initialize());
43 ATH_CHECK(m_outputRhoKey.initialize());
44 return StatusCode::SUCCESS;
45 }
46
47 StatusCode GTowerRhoSubtractionAlg::execute(const EventContext& ctx) const
48 {
49 auto inputTowers = SG::makeHandle(m_inputKey, ctx);
50 if (!inputTowers.isValid())
51 {
52 ATH_MSG_ERROR("Failed to retrieve input towers " << m_inputKey.key());
53 return StatusCode::FAILURE;
54 }
55 auto shallowCopy = xAOD::shallowCopyContainer(*inputTowers);
56 std::unique_ptr<xAOD::JGTowerContainer> outputTowers(shallowCopy.first);
57 std::unique_ptr<xAOD::ShallowAuxContainer> outputTowersAux(shallowCopy.second);
58 xAOD::setOriginalObjectLink(*inputTowers, *outputTowers);
59
60 // Split towers into FPGAs
61 constexpr static std::size_t nFPGAs = static_cast<std::size_t>(gFEX::FPGA::N_FPGAS);
62 std::array<std::vector<const xAOD::JGTower *>, nFPGAs> fpgas;
63 // Use histograms to calculate RMSs of tower Ets for each FPGA
64 std::array<TH1F, nFPGAs> fpgaHistograms;
65 std::vector<float> fpgaRhos(3, 0.0);
66 for (std::size_t i = 0; i < nFPGAs; ++i)
67 fpgaHistograms.at(i) = TH1F(("hFPGA" + std::to_string(i)).c_str(), "", 50, 0, 5000);
68 for (const xAOD::JGTower *tower : *inputTowers)
69 {
70 gFEX::FPGA fpga = gFEX::getFPGA(tower->eta());
71 if (fpga == gFEX::FPGA::N_FPGAS)
72 {
73 ATH_MSG_WARNING("Could not classify tower as an FPGA!");
74 continue;
75 }
76 fpgas.at(static_cast<std::size_t>(fpga)).push_back(tower);
77 fpgaHistograms.at(static_cast<std::size_t>(fpga)).Fill(tower->et());
78 }
79
80 // Now perform the subtraction
81 for (std::size_t i = 0; i < nFPGAs; ++i)
82 {
83 float threshold = 3 * fpgaHistograms.at(i).GetRMS();
84 const std::vector<const xAOD::JGTower *> &towers = fpgas.at(i);
85 float rho = calculateRho(towers);
86 fpgaRhos.at(i) = rho;
87 for (const xAOD::JGTower *tower : towers)
88 {
89 float area = accArea(*tower);
90 float etSub = tower->et() - area * rho;
91 // output is a shallow copy of input so the indices are guaranteed to be parallel
92 outputTowers->at(tower->index())->setEt(etSub < threshold ? 0 : etSub);
93 }
94 }
95
96 auto outputHandle = SG::makeHandle(m_outputKey, ctx);
97 ATH_CHECK(outputHandle.record(std::move(outputTowers), std::move(outputTowersAux)));
98
99 // Create an EnergySumRoI container to store the rho values
100 auto rhoCont = std::make_unique<xAOD::EnergySumRoI>();
101 auto rhoContAux = std::make_unique<xAOD::EnergySumRoIAuxInfo>();
102 rhoCont->setStore(rhoContAux.get());
103 decRho(*rhoCont) = std::move(fpgaRhos);
104 auto outputRhoHandle = SG::makeHandle(m_outputRhoKey, ctx);
105 ATH_CHECK(outputRhoHandle.record(std::move(rhoCont), std::move(rhoContAux)));
106 return StatusCode::SUCCESS;
107 }
108
109 float GTowerRhoSubtractionAlg::calculateRho(const std::vector<const xAOD::JGTower *> &towers) const
110 {
111 float totalEt = 0;
112 float totalArea = 0;
113 for (const xAOD::JGTower *tower : towers)
114 {
115 if ((m_useNegativeTowers || tower->et() > 0) && tower->et() <= m_maxTowerEt)
116 {
117 totalEt += tower->et();
118 totalArea += accArea(*tower);
119 }
120 }
121 float rho = (totalArea == 0 ? 0.0f : totalEt / totalArea);
122 if (m_forcePosRho && rho < 0)
123 rho = 0;
124 return rho;
125 }
126
127} // namespace LVL1
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_WARNING(x)
double area(double R)
Handle class for reading from StoreGate.
Handle class for recording to StoreGate.
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
An algorithm that can be simultaneously executed in multiple threads.
SG::WriteHandleKey< xAOD::JGTowerContainer > m_outputKey
virtual StatusCode execute(const EventContext &ctx) const override
virtual StatusCode initialize() override
SG::WriteHandleKey< xAOD::EnergySumRoI > m_outputRhoKey
GTowerRhoSubtractionAlg(const std::string &name, ISvcLocator *pSvcLocator)
float calculateRho(const std::vector< const xAOD::JGTower * > &towers) const
SG::ReadHandleKey< xAOD::JGTowerContainer > m_inputKey
SG::ConstAccessor< T, ALLOC > ConstAccessor
Definition AuxElement.h:569
SG::Decorator< T, ALLOC > Decorator
Definition AuxElement.h:575
FPGA getFPGA(float eta)
Get the FPGA code from the tower eta.
eFexTowerBuilder creates xAOD::eFexTowerContainer from supercells (LATOME) and triggerTowers (TREX) i...
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
std::pair< std::unique_ptr< T >, std::unique_ptr< ShallowAuxContainer > > shallowCopyContainer(const T &cont, const EventContext &ctx)
Function making a shallow copy of a constant container.
JGTower_v1 JGTower
Define the latest version of the JGTower class.
Definition JGTower.h:15
bool setOriginalObjectLink(const IParticle &original, IParticle &copy)
This function should be used by CP tools when they make a deep copy of an object in their correctedCo...