ATLAS Offline Software
Loading...
Searching...
No Matches
PFCellEOverPTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3*/
4
6#include "PFCellEOverPTool.h"
7#include "eflowCaloRegions.h"
8
9#include "GaudiKernel/SystemOfUnits.h"
10
12#include <nlohmann/json.hpp>
13
14#include <vector>
15#include <iomanip>
16#include <fstream>
17#include <sstream>
18
20 const std::string& name,
21 const IInterface* parent)
22 : IEFlowCellEOverPTool(type, name, parent)
23{
24
25 declareInterface<IEFlowCellEOverPTool>(this);
26
27}
28
30
31 std::string path;
33
34 ATH_MSG_INFO("Using reference file location " + path);
35
36 std::ifstream binBoundariesFile(path+"binBoundaries.json");
37 nlohmann::json json_binBoundaries;
38 binBoundariesFile >> json_binBoundaries;
39
40 //whilst for calo layers and first interaction regions we want to lookup the full set of bin values
41 auto fillBinValues = [](auto && binBoundaries, const nlohmann::json &json_binBoundaries, const std::string &binName){
42 if (json_binBoundaries.contains(binName)){
43 for (auto binBoundary : json_binBoundaries[binName]) binBoundaries.push_back(binBoundary);
44 return true;
45 }
46 else return false;
47 };
48
49 bool filledBins = false;
50 std::string energyBinBoundaries = "energyBinBoundaries";
51 std::string etaBinBoundaries = "etaBinBoundaries";
52 std::string firstIntBinBoundaries = "firstIntBinBoundaries";
53 std::string caloLayerBinBoundaries = "caloLayerBinBoundaries";
54
55 //here we verify we can load in the bin boundaries - if not we return a FAILURE code
56 //because particle flow cannot run correctly without these being loaded
57 filledBins = fillBinValues(m_energyBinLowerBoundaries, json_binBoundaries, energyBinBoundaries);
58 if (!filledBins) {
59 ATH_MSG_ERROR("Could not bin boundaries in json file: " << energyBinBoundaries);
60 return StatusCode::FAILURE;
61 }
62
63 //The e/p (mean, sigma) parameters are binned in track energy, track eta, calorimeter LHED and are derived using:
64 //https://gitlab.cern.ch/atlas-jetetmiss/pflow/commontools/EOverPTools/-/blob/main/EoverpNtupleAnalysis/Run_EoverP_Comparison.py?ref_type=heads
65
66
67 //The cell ordering parameters (norm1, sigma1, norm2, sigma2) are binned in the same way, and also in calo layer and are derived using:
68 //https://gitlab.cern.ch/atlas-jetetmiss/pflow/commontools/EOverPTools/-/blob/main/EoverpNtupleAnalysis/CellOrdering_Cpp.cxx?ref_type=heads
69
70 //The energy bins have a special treatment - if e.g if the last pair if boundaries are 40 and 100 GeV we measure e/p between those values, but we
71 //want to allow any track with e > 40 GeV to find an e/p reference value. Thus we remove the last bin boundary for the energy bins.
72
74
75 //We have to be careful with the eta bins. In this tool we don't want to use the last boundary value, because in this tool
76 //each eta bin value corresponds to the lower bin boundary and clearly you cannot move beyond the edge of the ID/ITK acceptance,
77 //so there is nothing to look up for the final bin. However in eflowEEtaBinnedParameters the same array is used to check the range
78 //in which an eta value falls. Thus we keep the final eta bin boundary in the array, but we have to be careful when looping over eta
79 //bins to not try to look up values for the final bin boundary value.
80
81 filledBins = fillBinValues(m_etaBinLowerBoundaries, json_binBoundaries, etaBinBoundaries);
82 if (!filledBins) {
83 ATH_MSG_ERROR("Could not bin boundaries in json file: " << etaBinBoundaries);
84 return StatusCode::FAILURE;
85 }
86
87 //The final two arrays correspond to specific calorimeter layes to look up parameters for, so this is like a key to look up
88 //rather than comparing a value to bin boundaries as is done for track energy and track eta.
89
90 filledBins = fillBinValues(m_firstIntBinLowerBoundaries, json_binBoundaries, firstIntBinBoundaries);
91 if (!filledBins) {
92 ATH_MSG_ERROR("Could not bin boundaries in json file: " << firstIntBinBoundaries);
93 return StatusCode::FAILURE;
94 }
95 filledBins = fillBinValues(m_caloLayerBins, json_binBoundaries, caloLayerBinBoundaries);
96 if (!filledBins) {
97 ATH_MSG_ERROR("Could not bin boundaries in json file: " << caloLayerBinBoundaries);
98 return StatusCode::FAILURE;
99 }
100
101 ATH_MSG_DEBUG("Energy bin boundaries: " << m_energyBinLowerBoundaries);
102 ATH_MSG_DEBUG("Eta bin boundaries: " << m_etaBinLowerBoundaries);
103 ATH_MSG_DEBUG("First interaction region bin boundaries: " << m_firstIntBinLowerBoundaries);
104 ATH_MSG_DEBUG("Calo layer bin boundaries: " << m_caloLayerBins);
105
106 return StatusCode::SUCCESS;
107}
108
110
111 if (binnedParameters) {
112
113 //The energy values in the json files are in GeV, but in athena we work in MeV
114 //so the energy values used by binnedParameters are converted to MeV
115 std::vector<double> energyBinLowerBoundaries_GeV;
116 for (auto energyBin : m_energyBinLowerBoundaries) energyBinLowerBoundaries_GeV.push_back(energyBin*Gaudi::Units::GeV);
117 binnedParameters->initialise(energyBinLowerBoundaries_GeV, m_etaBinLowerBoundaries);
118
119 std::string path;
121
122 std::ifstream inputFile_eoverp(path+"eOverP.json");
123 nlohmann::json json_eoverp;
124 inputFile_eoverp >> json_eoverp;
125
126 std::ifstream inputFile_cellOrdering(path+"cellOrdering.json");
127 nlohmann::json json_cellOrdering;
128 inputFile_cellOrdering >> json_cellOrdering;
129
130 //Loop over energy, eta and first int bins
131 //For each combination we set the e/p mean and width from the json file values
132 int energyBinCounter = -1;
133 for (auto thisEBin : m_energyBinLowerBoundaries){
134 energyBinCounter++;
135 std::stringstream currentEBinStream;
136 currentEBinStream << std::fixed << std::setprecision(0) << thisEBin;
137 std::string currentEBin = currentEBinStream.str();
138 int etaBinCounter = -1;
139 for (auto thisEtaBin : m_etaBinLowerBoundaries){
140 if (thisEtaBin == m_etaBinLowerBoundaries.back()) continue; //the last eta bin boundary is just used to define the upper edge of the final eta bin, so we don't need to fill parameters for it
141 etaBinCounter++;
142 std::stringstream currentEtaBinStream;
143 currentEtaBinStream << std::fixed << std::setprecision(1) << thisEtaBin;
144 std::string currentEtaBin = currentEtaBinStream.str();
145 for (auto thisFirstIntRegionBin_Int : m_firstIntBinLowerBoundaries){
146 //enum version is used for the calls to binnedParameters APIs
147 auto thisFirstIntRegionBin = static_cast<eflowFirstIntRegions::J1STLAYER>(thisFirstIntRegionBin_Int);
148 //and string version is used to lookup values from the json file
149 std::string currentFirstIntBin = std::to_string(thisFirstIntRegionBin_Int);
150 std::string eOverPBin = "energyBinLowerBound_"+currentEBin+"_etaBinLowerBound_"+currentEtaBin+"_firstIntBinLowerBound_"+currentFirstIntBin;
151 if (json_eoverp.contains(eOverPBin+"_mean")){
152 binnedParameters->setFudgeMean(energyBinCounter,etaBinCounter,thisFirstIntRegionBin,json_eoverp[eOverPBin+"_mean"]);
153 ATH_MSG_DEBUG("Setting mean for bin " << eOverPBin << " to " << json_eoverp[eOverPBin+"_mean"]);
154 }
155 //DEBUG because this is expected to happen for some combinations (e.g HEC calo layers for tracks in the barrel)
156 else ATH_MSG_DEBUG("No mean found for bin " << eOverPBin);
157 if (json_eoverp.contains(eOverPBin+"_sigma")){
158 binnedParameters->setFudgeStdDev(energyBinCounter,etaBinCounter,thisFirstIntRegionBin,json_eoverp[eOverPBin+"_sigma"]);
159 ATH_MSG_DEBUG("Setting sigma for bin " << eOverPBin << " to " << json_eoverp[eOverPBin+"_sigma"]);
160 }
161 else ATH_MSG_DEBUG("No sigma found for bin " << eOverPBin);
162 for (auto thisLayerBin : m_caloLayerBins){
163 eflowCalo::LAYER thisLayerBinEnum = static_cast<eflowCalo::LAYER>(thisLayerBin);
164 std::string currentLayerBin = eflowCalo::name(thisLayerBinEnum);
165 std::string cellOrderingBin = eOverPBin + "_caloLayer_"+std::to_string(thisLayerBin);
166 if (json_cellOrdering.contains(cellOrderingBin+"_norm1")){
167 binnedParameters->setShapeParam(energyBinCounter,etaBinCounter,thisFirstIntRegionBin,thisLayerBinEnum,NORM1,json_cellOrdering[cellOrderingBin+"_norm1"]);
168 ATH_MSG_DEBUG("Setting norm1 for bin " << cellOrderingBin << " to " << json_cellOrdering[cellOrderingBin+"_norm1"]);
169 }
170 else ATH_MSG_DEBUG("No norm1 found for bin " << cellOrderingBin);
171 if (json_cellOrdering.contains(cellOrderingBin+"_sigma1")){
172 binnedParameters->setShapeParam(energyBinCounter,etaBinCounter,thisFirstIntRegionBin,thisLayerBinEnum,WIDTH1,json_cellOrdering[cellOrderingBin+"_sigma1"]);
173 ATH_MSG_DEBUG("Setting sigma1 for bin " << cellOrderingBin << " to " << json_cellOrdering[cellOrderingBin+"_sigma1"]);
174 }
175 else ATH_MSG_DEBUG("No sigma1 found for bin " << cellOrderingBin);
176 if (json_cellOrdering.contains(cellOrderingBin+"_norm2")){
177 binnedParameters->setShapeParam(energyBinCounter,etaBinCounter,thisFirstIntRegionBin,thisLayerBinEnum,NORM2,json_cellOrdering[cellOrderingBin+"_norm2"]);
178 ATH_MSG_DEBUG("Setting norm2 for bin " << cellOrderingBin << " to " << json_cellOrdering[cellOrderingBin+"_norm2"]);
179 }
180 else ATH_MSG_DEBUG("No norm2 found for bin " << cellOrderingBin);
181 if (json_cellOrdering.contains(cellOrderingBin+"_sigma2")){
182 binnedParameters->setShapeParam(energyBinCounter,etaBinCounter,thisFirstIntRegionBin,thisLayerBinEnum,WIDTH2,json_cellOrdering[cellOrderingBin+"_sigma2"]);
183 ATH_MSG_DEBUG("Setting sigma2 for bin " << cellOrderingBin << " to " << json_cellOrdering[cellOrderingBin+"_sigma2"]);
184 }
185 else ATH_MSG_DEBUG("No sigma2 found for bin " << cellOrderingBin);
186 }
187 }
188 }
189 }
190 }
191
192 return StatusCode::SUCCESS;
193
194}
195
197 return StatusCode::SUCCESS;
198}
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_DEBUG(x)
std::string PathResolverFindCalibDirectory(const std::string &logical_file_name)
IEFlowCellEOverPTool(const std::string &type, const std::string &name, const IInterface *parent)
std::vector< int > m_firstIntBinLowerBoundaries
StatusCode initialize()
std::vector< double > m_etaBinLowerBoundaries
StatusCode fillBinnedParameters(eflowEEtaBinnedParameters *binnedParameters) const
std::vector< int > m_caloLayerBins
std::vector< double > m_energyBinLowerBoundaries
PFCellEOverPTool(const std::string &type, const std::string &name, const IInterface *parent)
Gaudi::Property< std::string > m_referenceFileLocation
Location for e/p and cell ordering reference files (set to null value so one cannot use a wrong refer...
static const std::string & name(LAYER layer)
Inherits from eflowEEtaBinBase.
void setFudgeStdDev(int energyBin, int etaBin, eflowFirstIntENUM j1st, double fudgeStdDev)
void setFudgeMean(int energyBin, int etaBin, eflowFirstIntENUM j1st, double fudgeMean)
void initialise(const std::vector< double > &eBinBounds, const std::vector< double > &etaBinBounds, bool useAbsEta=true)
void setShapeParam(int energyBin, int etaBin, eflowFirstIntENUM j1st, eflowCaloENUM layer, int paramNumber, double shapeParam)