ATLAS Offline Software
Loading...
Searching...
No Matches
GTowerRhoSubtractionAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 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 [outputTowers, outputTowersAux] = xAOD::shallowCopy(*inputTowers, ctx);
56 xAOD::setOriginalObjectLink(*inputTowers, *outputTowers);
57
58 // Split towers into FPGAs
59 constexpr static std::size_t nFPGAs = static_cast<std::size_t>(gFEX::FPGA::N_FPGAS);
60 std::array<std::vector<const xAOD::JGTower *>, nFPGAs> fpgas;
61 // Use histograms to calculate RMSs of tower Ets for each FPGA
62 std::array<TH1F, nFPGAs> fpgaHistograms;
63 std::vector<float> fpgaRhos(3, 0.0);
64 for (std::size_t i = 0; i < nFPGAs; ++i)
65 fpgaHistograms.at(i) = TH1F(("hFPGA" + std::to_string(i)).c_str(), "", 50, 0, 5000);
66 for (const xAOD::JGTower *tower : *inputTowers)
67 {
68 gFEX::FPGA fpga = gFEX::getFPGA(tower->eta());
69 if (fpga == gFEX::FPGA::N_FPGAS)
70 {
71 ATH_MSG_WARNING("Could not classify tower as an FPGA!");
72 continue;
73 }
74 fpgas.at(static_cast<std::size_t>(fpga)).push_back(tower);
75 fpgaHistograms.at(static_cast<std::size_t>(fpga)).Fill(tower->et());
76 }
77
78 // Now perform the subtraction
79 for (std::size_t i = 0; i < nFPGAs; ++i)
80 {
81 float threshold = 3 * fpgaHistograms.at(i).GetRMS();
82 const std::vector<const xAOD::JGTower *> &towers = fpgas.at(i);
83 float rho = calculateRho(towers);
84 fpgaRhos.at(i) = rho;
85 for (const xAOD::JGTower *tower : towers)
86 {
87 float area = accArea(*tower);
88 float etSub = tower->et() - area * rho;
89 // output is a shallow copy of input so the indices are guaranteed to be parallel
90 outputTowers->at(tower->index())->setEt(etSub < threshold ? 0 : etSub);
91 }
92 }
93
94 auto outputHandle = SG::makeHandle(m_outputKey, ctx);
95 ATH_CHECK(outputHandle.record(std::move(outputTowers), std::move(outputTowersAux)));
96
97 // Create an EnergySumRoI container to store the rho values
98 auto rhoCont = std::make_unique<xAOD::EnergySumRoI>();
99 auto rhoContAux = std::make_unique<xAOD::EnergySumRoIAuxInfo>();
100 rhoCont->setStore(rhoContAux.get());
101 decRho(*rhoCont) = std::move(fpgaRhos);
102 auto outputRhoHandle = SG::makeHandle(m_outputRhoKey, ctx);
103 ATH_CHECK(outputRhoHandle.record(std::move(rhoCont), std::move(rhoContAux)));
104 return StatusCode::SUCCESS;
105 }
106
107 float GTowerRhoSubtractionAlg::calculateRho(const std::vector<const xAOD::JGTower *> &towers) const
108 {
109 float totalEt = 0;
110 float totalArea = 0;
111 for (const xAOD::JGTower *tower : towers)
112 {
113 if ((m_useNegativeTowers || tower->et() > 0) && tower->et() <= m_maxTowerEt)
114 {
115 totalEt += tower->et();
116 totalArea += accArea(*tower);
117 }
118 }
119 float rho = (totalArea == 0 ? 0.0f : totalEt / totalArea);
120 if (m_forcePosRho && rho < 0)
121 rho = 0;
122 return rho;
123 }
124
125} // 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
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())
JGTower_v1 JGTower
Define the latest version of the JGTower class.
Definition JGTower.h:15
ShallowCopyResult_t< T > shallowCopy(const T &cont, const EventContext &ctx)
Create a shallow copy of an existing container.
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...