ATLAS Offline Software
EfexInputMonitorAlgorithm.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 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  if(!isPrescaled && eFexTowerContainer->empty()) {
108  Decision = "MissingDataTowers";
109  fill("errors", Decision,timeSince,timeUntil,evtNumber,lbn,lbnString,TowerId,Towereta,Towerphi,Toweremstatus,Towerhadstatus,TowerSlot,TowerCount,TowerRefCount,SlotSCID);
110  } else if(isPrescaled && !eFexTowerContainer->empty()) {
111  Decision = "UnexpectedDataTowers";
112  fill("errors", Decision,timeSince,timeUntil,evtNumber,lbn,lbnString,TowerId,Towereta,Towerphi,Toweremstatus,Towerhadstatus,TowerSlot,TowerCount,TowerRefCount,SlotSCID);
113  }
114 
115  if(eFexTowerContainer->empty()) return StatusCode::SUCCESS; // don't do the rest of the monitoring unless processing a DataTowers event
116 
117 
118  // Access eFexTower ref container, if possible
120  auto etaIndex = [](float eta) { return int( eta*10 ) + ((eta<0) ? -1 : 1); };
121  auto phiIndex = [](float phi) { return int( phi*32./M_PI ) + (phi<0 ? -1 : 1); };
122  std::map<std::pair<int,int>,const xAOD::eFexTower*> refTowers;
123  bool missingLAr = false;
124  if (eFexTowerContainerRef.isValid()) {
125  if(eFexTowerContainerRef->empty()) missingLAr=true;
126  for (auto eTower: *eFexTowerContainerRef) {
127  refTowers[std::pair(etaIndex(eTower->eta() + 0.025), phiIndex(eTower->phi() + 0.025))] = eTower;
128  // fill profile histograms for each layer (ECAL,HCAL) so that we can identify when a layer is being noisy
129  Towereta = eTower->eta(); Towerphi = eTower->phi();
130  std::vector<uint16_t> Toweret_count=eTower->et_count();
131  for(size_t i=0;i<Toweret_count.size();i++) {
132  TowerRefCount = Toweret_count[i];
133  if (TowerRefCount==1025) missingLAr=true; // 1025 comes from eFexTowerBuilder if it had no supercells
134  if(TowerRefCount==1025 || TowerRefCount==1022) TowerRefCount=0; // unavailable or invalid code
135  fill((i<10) ? "ecal" : "hcal",lbn,Towereta,Towerphi,TowerRefCount);
136  }
137  }
138  }
139  if(missingLAr) {
140  Decision = "MissingSCells";
141  fill("errors", Decision,timeSince,timeUntil,evtNumber,lbn,lbnString,TowerId,Towereta,Towerphi,Toweremstatus,Towerhadstatus,TowerSlot,TowerCount,TowerRefCount,SlotSCID);
142  }
143 
144 
145 
146  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)
147 
148  auto IsMonReady = Monitored::Scalar<bool>("IsMonReady",true); // used to fill into eta/phi map only certain types of error.
149  auto OnPed = Monitored::Scalar<double>("OnPedestal",0.);
150  auto AboveCut = Monitored::Scalar<bool>("AboveCut",false);
151  auto BelowCut = Monitored::Scalar<bool>("BelowCut",false);
152  auto binNumber = Monitored::Scalar<int>("binNumber",0);
153 
154  for(const xAOD::eFexTower* eTower : *eFexTowerContainer) {
155  TowerId = eTower->id();
156  Towereta=eTower->eta();
157  Towerphi=eTower->phi();
158  Toweremstatus=eTower->em_status();
159  Towerhadstatus=eTower->had_status();
160  if(eTower->em_status()) {
161  Decision="BadEMStatus";
162  ErrorAndLocation = std::string("#splitline{") + Decision + "}{" + std::to_string(TowerId) + "}";
163  fill("errors",Decision,ErrorAndLocation,timeSince,timeUntil,evtNumber,lbn,lbnString,TowerId,Towereta,Towerphi,Toweremstatus,Towerhadstatus,TowerSlot,TowerCount,TowerRefCount,SlotSCID,IsMonReady);
164  }
165  if(eTower->had_status()) {
166  Decision="BadHadStatus";
167  ErrorAndLocation = std::string("#splitline{") + Decision + "}{" + std::to_string(TowerId) + "}";
168  fill("errors",Decision,ErrorAndLocation,timeSince,timeUntil,evtNumber,lbn,lbnString,TowerId,Towereta,Towerphi,Toweremstatus,Towerhadstatus,TowerSlot,TowerCount,TowerRefCount,SlotSCID,IsMonReady);
169  }
170  std::vector<uint16_t> counts=eTower->et_count();
171  std::vector<uint16_t> refcounts;
172  auto coord = std::pair(etaIndex(eTower->eta() + 0.025), phiIndex(eTower->phi() + 0.025));
173  if(!refTowers.empty()) {
174  if(auto itr = refTowers.find(coord); itr != refTowers.end()) {
175  refcounts = itr->second->et_count();
176  }
177  }
178  for(size_t i=0;i<counts.size();i++) {
179  if (eTower->disconnectedCount(i)) continue; // skip disconnected counts
180  // only do each tower once (skip duplications across modules)
181  if (doneCounts.find(std::pair(coord,i))==doneCounts.end()) {
182  doneCounts.insert(std::pair(coord,i));
183  } else {
184  continue;
185  }
186  bool isLAr = !(i==10 && std::abs(Towereta)<=1.5);
187  TowerSlot = i;
188  TowerCount = counts[i];
189  TowerRefCount = -1;
190  Decision = "";
191  if(!refTowers.empty()) { // only do slot-by-slot comparison if we actually have ref towers
192  if(refcounts.size() != counts.size()) {
193  Decision = "NumSlotMismatch";
194  } else {
195  TowerRefCount = refcounts.at(i);
196  if(isLAr) {
197  if(TowerCount==1022) {
198  Decision = "LArInvalidCode";
199  if(TowerRefCount!=1022) {
200  Decision = "LArInvalidCodeMismatched";
201  }
202  } else if(!TowerCount && TowerRefCount) {
203  Decision="LArMissingMask";
204  } else if(TowerCount && !TowerRefCount) {
205  Decision="LArExtraMask";
206  } else if(TowerCount != TowerRefCount) {
207  Decision="LArMismatch";
208  }
209  // should we also monitor saturations (code 1023?)
210  } else if(TowerCount != TowerRefCount) {
211  Decision="TileMismatch";
212  }
213  }
214  if(!std::string(Decision).empty()) {
215  if(isLAr) {
216  if (auto itr = m_scMap.find(std::make_pair(coord, i)); itr != m_scMap.end()) {
217  SlotSCID = itr->second.second;
218  }
219  }
220  ErrorAndLocation = std::string("#splitline{") + Decision + "}{" + std::to_string(TowerId) + "}";
221  fill("errors",Decision,ErrorAndLocation,timeSince,timeUntil,evtNumber,lbn,lbnString,TowerId,Towereta,Towerphi,Toweremstatus,Towerhadstatus,TowerSlot,TowerCount,TowerRefCount,SlotSCID);
222  }
223  }
224  // since lar invalid codes will be treated as a 0 energy, don't fill into plot
225  if ((!isLAr) || (TowerCount != 1022)) {
226  AboveCut = (TowerCount >= (isLAr ? 52:1)); // count of 52 ~= 500 MeV
227  BelowCut = (TowerCount < (isLAr ? 23:0) && TowerCount>0); // count of 22 ~= -500 MeV
228  if(AboveCut || BelowCut) {
229  int etaIdx = TowerId/100000;
230  if(etaIdx>0) etaIdx--; // so goes from -25 to 24
231  int phiIdx = std::abs(TowerId % 100000)/1000;
232  if(phiIdx>31) phiIdx -= 64; // so goes from -32 to 31
233  binNumber = (phiIdx+32)*50 + 26 + etaIdx; // = 50*(y-1)+x as displayed in standard histogram
234  fill((i<10) ? "ecal" : "hcal",lbn,Towereta,Towerphi,TowerCount,AboveCut,BelowCut,binNumber);
235  }
236  }
237  }
238  }
239 
240 
241  return StatusCode::SUCCESS;
242 }
243 
244 
python.SystemOfUnits.s
int s
Definition: SystemOfUnits.py:131
SG::ReadCondHandle
Definition: ReadCondHandle.h:44
EfexInputMonitorAlgorithm::m_eFexTowerContainerKey
SG::ReadHandleKey< xAOD::eFexTowerContainer > m_eFexTowerContainerKey
Definition: EfexInputMonitorAlgorithm.h:29
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
xAOD::eFexTower_v1
Class describing input data of a LVL1 eFEX.
Definition: eFexTower_v1.h:22
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:70
min
constexpr double min()
Definition: ap_fixedTest.cxx:26
EfexInputMonitorAlgorithm::m_packageName
StringProperty m_packageName
Definition: EfexInputMonitorAlgorithm.h:26
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:32
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
FortranAlgorithmOptions.fileName
fileName
Definition: FortranAlgorithmOptions.py:13
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
lumiFormat.i
int i
Definition: lumiFormat.py:85
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:135
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:30
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
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:39
EfexInputMonitorAlgorithm.h
JetVoronoiDiagramHelpers::coord
double coord
Definition: JetVoronoiDiagramHelpers.h:45
PathResolverFindCalibFile
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
Definition: PathResolver.cxx:431
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
Monitored::Scalar
Declare a monitored scalar variable.
Definition: MonitoredScalar.h:34
xAOD::lumiBlock
setTeId lumiBlock
Definition: L2StandAloneMuon_v1.cxx:327
DataVector::empty
bool empty() const noexcept
Returns true if the collection is empty.
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37