ATLAS Offline Software
EfexInputMonitorAlgorithm.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 #include "TTree.h"
8 #include "TFile.h"
9 
10 EfexInputMonitorAlgorithm::EfexInputMonitorAlgorithm( const std::string& name, ISvcLocator* pSvcLocator )
11  : AthMonitorAlgorithm(name,pSvcLocator)
12 {
13 }
14 
16 
17  ATH_MSG_DEBUG("EfexInputMonitorAlgorith::initialize");
18  ATH_MSG_DEBUG("Package Name "<< m_packageName);
19  ATH_MSG_DEBUG("m_eFexTowerContainer"<< m_eFexTowerContainerKey);
20 
21  // we initialise all the containers that we need
22  ATH_CHECK( m_eFexTowerContainerKey.initialize() );
23  ATH_CHECK( m_eFexTowerContainerRefKey.initialize() );
24 
25  ATH_CHECK( m_bcContKey.initialize() );
26 
27 
28  // load the scid map
29  if (auto fileName = PathResolverFindCalibFile( "L1CaloFEXByteStream/2023-02-13/scToEfexTowers.root" ); !fileName.empty()) {
30  std::unique_ptr<TFile> f( TFile::Open(fileName.c_str()) );
31  if (f) {
32  TTree* t = f->Get<TTree>("mapping");
33  if(t) {
34  unsigned long long scid = 0;
35  std::pair<int,int> coord = {0,0};
36  std::pair<int,int> slot;
37  t->SetBranchAddress("scid",&scid);
38  t->SetBranchAddress("etaIndex",&coord.first);
39  t->SetBranchAddress("phiIndex",&coord.second);
40  t->SetBranchAddress("slot1",&slot.first);
41  t->SetBranchAddress("slot2",&slot.second);
42  for(Long64_t i=0;i<t->GetEntries();i++) {
43  t->GetEntry(i);
44  m_scMap[std::make_pair(coord,slot.first)].first.insert(scid);
45  m_scMap[std::make_pair(coord,slot.second)].first.insert(scid);
46  }
47  // now convert scid list to list of strings
48  for(auto& [key,scs] : m_scMap) {
49  std::stringstream s;
50  for(auto id : scs.first) {
51  s << (id>>32) << ",";
52  }
53  scs.second = s.str();
54  scs.first.clear(); // not needed any more, so clear it
55  }
56  }
57  }
58  }
59 
60 
61 
62 
64 }
65 
66 StatusCode EfexInputMonitorAlgorithm::fillHistograms( const EventContext& ctx ) const {
67 
68  ATH_MSG_DEBUG("EfexInputMonitorAlgorithm::fillHistograms");
69 
70  // Access eFex eTower container - should always have a collection, even if empty
72  if(!eFexTowerContainer.isValid()){
73  ATH_MSG_ERROR("No eFex Tower container found in storegate "<< m_eFexTowerContainerKey);
74  return StatusCode::FAILURE;
75  }
76 
77 
78  auto evtNumber = Monitored::Scalar<ULong64_t>("EventNumber",GetEventInfo(ctx)->eventNumber());
79  auto lbnString = Monitored::Scalar<std::string>("LBNString",std::to_string(GetEventInfo(ctx)->lumiBlock()));
80  auto lbn = Monitored::Scalar<int>("LBN",GetEventInfo(ctx)->lumiBlock());
81 
82  // mismatches can be caused by recent/imminent OTF maskings, so track timings
83  auto timeSince = Monitored::Scalar<int>("timeSince", -1);
84  auto timeUntil = Monitored::Scalar<int>("timeUntil", -1);
85  auto timeUntilCapped = Monitored::Scalar<int>("timeUntilCapped", -1); // capped at 199 for histograms
87  if(larBadChan.isValid()) {
88  timeSince = ctx.eventID().time_stamp() - larBadChan.getRange().start().time_stamp();
89  timeUntil = larBadChan.getRange().stop().time_stamp() - ctx.eventID().time_stamp();
90  timeUntilCapped = std::min(int(timeUntil),199);
91  }
92  auto Decision = Monitored::Scalar<std::string>("Error","");
93  auto ErrorAndLocation = Monitored::Scalar<std::string>("ErrorAndLocation","");
94 
95  auto TowerId = Monitored::Scalar<int32_t>("TowerId",0);
96  auto Towereta = Monitored::Scalar<float>("TowerEta",0.0);
97  auto Towerphi = Monitored::Scalar<float>("TowerPhi",0.0);
98  auto TowerRefCount = Monitored::Scalar<int>("RefTowerCount",0);
99  auto Toweremstatus = Monitored::Scalar<uint32_t>("TowerEmstatus",0);
100  auto Towerhadstatus = Monitored::Scalar<uint32_t>("TowerHadstatus",0);
101  auto TowerSlot = Monitored::Scalar<int32_t>("TowerSlot",0);
102  auto TowerCount = Monitored::Scalar<int>("TowerCount",0);
103  auto SlotSCID = Monitored::Scalar<std::string>("SlotSCID","");
104 
105  // first test dataTowers not empty unless prescaled event
106  bool isPrescaled = (((GetEventInfo(ctx)->extendedLevel1ID()&0xffffff) % 200) != 0);
107  size_t badTowers = 0;
108  if(!isPrescaled && eFexTowerContainer->empty()) {
109  Decision = "MissingDataTowers";
110  fill("errors", Decision,timeSince,timeUntil,evtNumber,lbn,lbnString,TowerId,Towereta,Towerphi,Toweremstatus,Towerhadstatus,TowerSlot,TowerCount,TowerRefCount,SlotSCID);
111  } else if(isPrescaled && !eFexTowerContainer->empty()) {
112  // check if all the towers have errors, if so then this readout IS expected
113  for(auto eFexTower : *eFexTowerContainer) {
114  if(eFexTower->em_status()||eFexTower->had_status()) badTowers++;
115  }
116  if(badTowers != eFexTowerContainer->size()) {
117  Decision = "UnexpectedDataTowers";
118  fill("errors", Decision, timeSince, timeUntil, evtNumber, lbn, lbnString, TowerId, Towereta, Towerphi,
119  Toweremstatus, Towerhadstatus, TowerSlot, TowerCount, TowerRefCount, SlotSCID);
120  }
121  }
122 
123  if(eFexTowerContainer->empty() || badTowers==eFexTowerContainer->size()) return StatusCode::SUCCESS; // don't do the rest of the monitoring unless processing a DataTowers event
124 
125 
126  // Access eFexTower ref container, if possible
128  auto etaIndex = [](float eta) { return int( eta*10 ) + ((eta<0) ? -1 : 1); };
129  auto phiIndex = [](float phi) { return int( phi*32./M_PI ) + (phi<0 ? -1 : 1); };
130  std::map<std::pair<int,int>,const xAOD::eFexTower*> refTowers;
131  size_t missingSlots = 0;
132  if (eFexTowerContainerRef.isValid()) {
133  if(eFexTowerContainerRef->empty()) missingSlots=34048;
134  for (auto eTower: *eFexTowerContainerRef) {
135  refTowers[std::pair(etaIndex(eTower->eta() + 0.025), phiIndex(eTower->phi() + 0.025))] = eTower;
136  // fill profile histograms for each layer (ECAL,HCAL) so that we can identify when a layer is being noisy
137  Towereta = eTower->eta(); Towerphi = eTower->phi();
138  std::vector<uint16_t> Toweret_count=eTower->et_count();
139  for(size_t i=0;i<Toweret_count.size();i++) {
140  TowerRefCount = Toweret_count[i];
141  if (TowerRefCount==1025) missingSlots+=1; // 1025 comes from eFexTowerBuilder if it had no supercells
142  if(TowerRefCount==1025 || TowerRefCount==1022) TowerRefCount=0; // unavailable or invalid code
143  fill((i<10) ? "ecal" : "hcal",lbn,Towereta,Towerphi,TowerRefCount);
144  }
145  }
146  }
147  if(missingSlots > 1280) { /*expect 1280 unfilled slots in a normal event*/
148  Decision = "MissingSCells";
149  fill("errors", Decision,timeSince,timeUntil,evtNumber,lbn,lbnString,TowerId,Towereta,Towerphi,Toweremstatus,Towerhadstatus,TowerSlot,TowerCount,TowerRefCount,SlotSCID);
150  ATH_MSG_WARNING(std::string(Decision) << " in event " << evtNumber << " in lb " << std::string(lbnString));
151  }
152 
153 
154 
155  std::set<std::pair<std::pair<int,int>,int>> doneCounts; // only fill each count once (there are duplicates in DataTowers readout b.c. of module overlap)
156 
157  auto IsMonReady = Monitored::Scalar<bool>("IsMonReady",true); // used to fill into eta/phi map only certain types of error.
158  auto OnPed = Monitored::Scalar<double>("OnPedestal",0.);
159  auto AboveCut = Monitored::Scalar<bool>("AboveCut",false);
160  auto BelowCut = Monitored::Scalar<bool>("BelowCut",false);
161  auto binNumber = Monitored::Scalar<int>("binNumber",0);
162 
163  std::set<std::string> reportedErrors;
164 
165  for(const xAOD::eFexTower* eTower : *eFexTowerContainer) {
166  TowerId = eTower->id();
167  Towereta=eTower->eta();
168  Towerphi=eTower->phi();
169  Toweremstatus=eTower->em_status();
170  Towerhadstatus=eTower->had_status();
171  if(eTower->em_status()) {
172  Decision="BadEMStatus";
173  ErrorAndLocation = "#splitline{" + static_cast<std::string>(Decision) + "}{" + std::to_string(TowerId) + "}";
174  fill("errors",Decision,ErrorAndLocation,timeSince,timeUntil,evtNumber,lbn,lbnString,TowerId,Towereta,Towerphi,Toweremstatus,Towerhadstatus,TowerSlot,TowerCount,TowerRefCount,SlotSCID,IsMonReady);
175  if(!reportedErrors.count(Decision)) {
176  ATH_MSG_WARNING(std::string(Decision) << " in event " << evtNumber << " in lb " << std::string(lbnString));
177  reportedErrors.insert(Decision);
178  }
179  }
180  if(eTower->had_status()) {
181  Decision="BadHadStatus";
182  ErrorAndLocation = "#splitline{" + static_cast<std::string>(Decision) + "}{" + std::to_string(TowerId) + "}";
183  fill("errors",Decision,ErrorAndLocation,timeSince,timeUntil,evtNumber,lbn,lbnString,TowerId,Towereta,Towerphi,Toweremstatus,Towerhadstatus,TowerSlot,TowerCount,TowerRefCount,SlotSCID,IsMonReady);
184  if(!reportedErrors.count(Decision)) {
185  ATH_MSG_WARNING(std::string(Decision) << " in event " << evtNumber << " in lb " << std::string(lbnString));
186  reportedErrors.insert(Decision);
187  }
188  }
189  std::vector<uint16_t> counts=eTower->et_count();
190  std::vector<uint16_t> refcounts;
191  auto coord = std::pair(etaIndex(eTower->eta() + 0.025), phiIndex(eTower->phi() + 0.025));
192  if(!refTowers.empty()) {
193  if(auto itr = refTowers.find(coord); itr != refTowers.end()) {
194  refcounts = itr->second->et_count();
195  }
196  }
197  for(size_t i=0;i<counts.size();i++) {
198  if (eTower->disconnectedCount(i)) continue; // skip disconnected counts
199  // only do each tower once (skip duplications across modules)
200  if (doneCounts.find(std::pair(coord,i))==doneCounts.end()) {
201  doneCounts.insert(std::pair(coord,i));
202  } else {
203  continue;
204  }
205  bool isLAr = !(i==10 && std::abs(Towereta)<=1.5);
206  if(counts[i]==1025) {
207  // 1025 is the code used by bytestream decoder if there is no input for that slot
208  if(isLAr) {
209  if (auto itr = m_scMap.find(std::make_pair(coord, i)); itr != m_scMap.end()) {
210  SlotSCID = itr->second.second;
211  }
212  Decision = "MissingLAr";
213  fill("errors", Decision,timeSince,timeUntil,evtNumber,lbn,lbnString,TowerId,Towereta,Towerphi,Toweremstatus,Towerhadstatus,TowerSlot,TowerCount,TowerRefCount,SlotSCID,IsMonReady);
214  if(!reportedErrors.count(Decision)) {
215  ATH_MSG_WARNING(std::string(Decision) << " in event " << evtNumber << " in lb " << std::string(lbnString));
216  reportedErrors.insert(Decision);
217  }
218  } else {
219  Decision = "MissingTile";
220  SlotSCID="";
221  fill("errors", Decision,timeSince,timeUntil,evtNumber,lbn,lbnString,TowerId,Towereta,Towerphi,Toweremstatus,Towerhadstatus,TowerSlot,TowerCount,TowerRefCount,SlotSCID,IsMonReady);
222  if(!reportedErrors.count(Decision)) {
223  ATH_MSG_WARNING(std::string(Decision) << " in event " << evtNumber << " in lb " << std::string(lbnString));
224  reportedErrors.insert(Decision);
225  }
226  }
227  continue;
228  }
229  TowerSlot = i;
230  TowerCount = counts[i];
231  TowerRefCount = -1;
232  Decision = "";
233  if(!refTowers.empty()) { // only do slot-by-slot comparison if we actually have ref towers
234  if(refcounts.size() != counts.size()) {
235  Decision = "NumSlotMismatch";
236  } else {
237  TowerRefCount = refcounts.at(i);
238  if(isLAr) {
239  if(TowerCount==1022) {
240  //Decision = "LArInvalidCode"; - not an error, or at least not one we (L1Calo) should be tracking for now
241  if(TowerRefCount!=1022) {
242  Decision = "LArInvalidCodeMismatched";
243  }
244  } else if(!TowerCount && TowerRefCount) {
245  Decision="LArMissingMask";
246  } else if(TowerCount && !TowerRefCount) {
247  Decision="LArExtraMask";
248  } else if(TowerCount != TowerRefCount) {
249  if(TowerRefCount==1025) {
250  Decision = "MissingRefLAr";
251  } else {
252  Decision = "LArMismatch";
253  }
254  }
255  // should we also monitor saturations (code 1023?)
256  } else if(TowerCount != TowerRefCount) {
257  if(TowerRefCount==1025) {
258  Decision = "MissingRefTile";
259  } else {
260  Decision="TileMismatch";
261  }
262  }
263  }
264  if(!std::string(Decision).empty()) {
265  if(isLAr) {
266  if (auto itr = m_scMap.find(std::make_pair(coord, i)); itr != m_scMap.end()) {
267  SlotSCID = itr->second.second;
268  }
269  }
270  if(!(isLAr && timeUntil>=0 && timeUntil<=5)) { // lar errors within 5s of an otf masking update are not treated as errors
271  ErrorAndLocation = "#splitline{" + static_cast<std::string>(Decision) + "}{" + std::to_string(TowerId) + "}";
272  fill("errors", Decision, ErrorAndLocation, timeSince, timeUntil, evtNumber, lbn, lbnString,
273  TowerId, Towereta, Towerphi, Toweremstatus, Towerhadstatus, TowerSlot, TowerCount,
274  TowerRefCount, SlotSCID,IsMonReady);
275  if (!reportedErrors.count(Decision)) {
276  ATH_MSG_WARNING(std::string(Decision) << " in event " << evtNumber << " in lb "
277  << std::string(lbnString));
278  reportedErrors.insert(Decision);
279  }
280  }
281  }
282  }
283  // since lar invalid codes will be treated as a 0 energy, don't fill into plot
284  if ((!isLAr) || (TowerCount != 1022)) {
285  AboveCut = (TowerCount >= (isLAr ? 52:1)); // count of 52 ~= 500 MeV
286  BelowCut = (TowerCount < (isLAr ? 23:0) && TowerCount>0); // count of 22 ~= -500 MeV
287  if(AboveCut || BelowCut) {
288  int etaIdx = TowerId/100000;
289  if(etaIdx>0) etaIdx--; // so goes from -25 to 24
290  int phiIdx = std::abs(TowerId % 100000)/1000;
291  if(phiIdx>31) phiIdx -= 64; // so goes from -32 to 31
292  binNumber = (25 + etaIdx)*64 + phiIdx+33; // = 64*(x-1)+y as displayed in standard histogram
293  fill((i<10) ? "ecal" : "hcal",lbn,Towereta,Towerphi,TowerCount,AboveCut,BelowCut,binNumber);
294  }
295  }
296  }
297  }
298 
299 
300  return StatusCode::SUCCESS;
301 }
302 
303 
phi
Scalar phi() const
phi method
Definition: AmgMatrixBasePlugin.h:67
SG::ReadCondHandle
Definition: ReadCondHandle.h:44
EfexInputMonitorAlgorithm::m_eFexTowerContainerKey
SG::ReadHandleKey< xAOD::eFexTowerContainer > m_eFexTowerContainerKey
Definition: EfexInputMonitorAlgorithm.h:31
xAOD::eFexTower_v1
Class describing input data of a LVL1 eFEX.
Definition: eFexTower_v1.h:22
eta
Scalar eta() const
pseudorapidity method
Definition: AmgMatrixBasePlugin.h:83
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:67
min
constexpr double min()
Definition: ap_fixedTest.cxx:26
EfexInputMonitorAlgorithm::m_packageName
StringProperty m_packageName
Definition: EfexInputMonitorAlgorithm.h:28
xAOD::eFexTower
eFexTower_v1 eFexTower
Define the latest version of the TriggerTower class.
Definition: eFexTower.h:15
EfexInputMonitorAlgorithm::m_scMap
std::map< std::pair< std::pair< int, int >, int >, std::pair< std::set< unsigned long long >, std::string > > m_scMap
Definition: EfexInputMonitorAlgorithm.h:34
M_PI
#define M_PI
Definition: ActiveFraction.h:11
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
EfexInputMonitorAlgorithm::fillHistograms
virtual StatusCode fillHistograms(const EventContext &ctx) const override
adds event to the monitoring histograms
Definition: EfexInputMonitorAlgorithm.cxx:66
AthMonitorAlgorithm
Base class for Athena Monitoring Algorithms.
Definition: AthMonitorAlgorithm.h:36
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
xAOD::eFexTowerContainer
eFexTowerContainer_v1 eFexTowerContainer
Define the latest version of the TriggerTower container.
Definition: eFexTowerContainer.h:14
xAOD::eFexTower_v1::em_status
uint32_t em_status() const
get em status bit
lumiFormat.i
int i
Definition: lumiFormat.py:85
L1TopoRatesCalculator_submatrix_plotter.counts
counts
Definition: L1TopoRatesCalculator_submatrix_plotter.py:74
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
hist_file_dump.f
f
Definition: hist_file_dump.py:140
xAOD::eventNumber
eventNumber
Definition: EventInfo_v1.cxx:124
AthMonitorAlgorithm::fill
void fill(const ToolHandle< GenericMonitoringTool > &groupHandle, std::vector< std::reference_wrapper< Monitored::IMonitoredVariable >> &&variables) const
Fills a vector of variables to a group by reference.
AthMonitorAlgorithm::GetEventInfo
SG::ReadHandle< xAOD::EventInfo > GetEventInfo(const EventContext &) const
Return a ReadHandle for an EventInfo object (get run/event numbers, etc.)
Definition: AthMonitorAlgorithm.cxx:107
PathResolver.h
EfexInputMonitorAlgorithm::m_eFexTowerContainerRefKey
SG::ReadHandleKey< xAOD::eFexTowerContainer > m_eFexTowerContainerRefKey
Definition: EfexInputMonitorAlgorithm.h:32
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
xAOD::eFexTower_v1::had_status
uint32_t had_status() const
setter for the above
ActsTrk::to_string
std::string to_string(const DetectorType &type)
Definition: GeometryDefs.h:34
TrigCompositeUtils::Decision
xAOD::TrigComposite Decision
Definition: Event/xAOD/xAODTrigger/xAODTrigger/TrigComposite.h:20
EfexInputMonitorAlgorithm::m_bcContKey
SG::ReadCondHandleKey< LArBadChannelCont > m_bcContKey
Definition: EfexInputMonitorAlgorithm.h:41
EfexInputMonitorAlgorithm.h
JetVoronoiDiagramHelpers::coord
double coord
Definition: JetVoronoiDiagramHelpers.h:45
PathResolverFindCalibFile
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
Definition: PathResolver.cxx:283
AthMonitorAlgorithm::initialize
virtual StatusCode initialize() override
initialize
Definition: AthMonitorAlgorithm.cxx:18
eflowRec::phiIndex
unsigned int phiIndex(float phi, float binsize)
calculate phi index for a given phi
Definition: EtaPhiLUT.cxx:23
EfexInputMonitorAlgorithm::EfexInputMonitorAlgorithm
EfexInputMonitorAlgorithm(const std::string &name, ISvcLocator *pSvcLocator)
Definition: EfexInputMonitorAlgorithm.cxx:10
EfexInputMonitorAlgorithm::initialize
virtual StatusCode initialize() override
initialize
Definition: EfexInputMonitorAlgorithm.cxx:15
python.CaloAddPedShiftConfig.int
int
Definition: CaloAddPedShiftConfig.py:45
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
python.SystemOfUnits.s
float s
Definition: SystemOfUnits.py:147
jobOptions.fileName
fileName
Definition: jobOptions.SuperChic_ALP2.py:39
Monitored::Scalar
Declare a monitored scalar variable.
Definition: MonitoredScalar.h:34
xAOD::lumiBlock
setTeId lumiBlock
Definition: L2StandAloneMuon_v1.cxx:328
DataVector::size
size_type size() const noexcept
Returns the number of elements in the collection.
DataVector::empty
bool empty() const noexcept
Returns true if the collection is empty.
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37