ATLAS Offline Software
Loading...
Searching...
No Matches
LArNoisyROTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5// LArNoisyROTool.cxx
6// Implementation file for class LArNoisyROTool
8
9// LArCellRec includes
10#include "LArNoisyROTool.h"
11
19
20// Athena algtool's Hooks
23
25 ATH_MSG_FATAL( "Configuration problem: LArNoisyROTool assumes that the QFactor cut to declare a channel noisy is softer than the QFactor cut to declare the quality saturated !" );
26 return StatusCode::FAILURE;
27 }
28
30 ATH_MSG_FATAL( "Configuration problem: LArNoisyROTool assumes that MNBLooseCut is smaller than MNBTightCut" );
31 return StatusCode::FAILURE;
32 }
33
34 ATH_CHECK(detStore()->retrieve(m_calo_id,"CaloCell_ID"));
35 ATH_CHECK(detStore()->retrieve(m_onlineID,"LArOnlineID"));
36 ATH_CHECK(detStore()->retrieve(m_elecID,"LArElectrodeID"));
37 ATH_CHECK( m_cablingKey.initialize() );
38
39 // Fill the map between any EMB FEB and the same FT PS FEB
40 // Filled only for EMB so far
41 for (std::vector<HWIdentifier>::const_iterator allFeb = m_onlineID->feb_begin();
42 allFeb != m_onlineID->feb_end(); ++allFeb) {
43
44 HWIdentifier febid = HWIdentifier(*allFeb);
45 int FEBIndex = febid.get_identifier32().get_compact();
46 int FEBIndex_PS = 0;
47 int barrel_ec = m_onlineID->barrel_ec(febid);
48 if (barrel_ec == 0){
49 int pos_neg = m_onlineID->pos_neg(febid);
50 int ft = m_onlineID->feedthrough(febid);
51 FEBIndex_PS = (m_onlineID->feb_Id(0,pos_neg,ft,1)).get_identifier32().get_compact();
52 }
53 m_mapPSFEB[FEBIndex] = FEBIndex_PS;
54 }
55
56 return StatusCode::SUCCESS;
57}
58
59
60std::unique_ptr<LArNoisyROSummary> LArNoisyROTool::process(const EventContext& ctx, const CaloCellContainer* cellContainer, const std::set<unsigned int>* knownBadFEBs, const std::vector<HWIdentifier>* knownMNBFEBs, const LArHVNMap* nCellsperLine, const CaloDetDescrManager* cddm, const LArHVIdMapping* hvid) const{
61
62 // sanity check
63 bool doHVline=m_doHVline;
64 if(doHVline && ( !nCellsperLine || !cddm || !hvid)) {
65 ATH_MSG_ERROR("HV line flagging asked, but missing ingrediences, switching off !!");
66 doHVline = false;
67 }
68
69 std::unique_ptr<LArNoisyROSummary> noisyRO=std::make_unique<LArNoisyROSummary>();
70
71 if(!cellContainer) return noisyRO;
72
74 const LArOnOffIdMapping* cabling=*larCablingHdl;
75
76 FEBEvtStatMap FEBStats; //counter per FEB
77 HVlinesStatMap HVStats; //counter per HV line
78
79 unsigned int NsaturatedTightCutBarrelA = 0;
80 unsigned int NsaturatedTightCutBarrelC = 0;
81 unsigned int NsaturatedTightCutEMECA = 0;
82 unsigned int NsaturatedTightCutEMECC = 0;
83
84 for (const CaloCell* cell : *cellContainer )
85 {
86 if (!cell) continue;
87
88 // only cells with a bad enough Quality Factor
89 if ( cell->quality() < m_CellQualityCut ) continue;
90
91 // cells with zero energy have been masked by previous algorithms
92 // they should not matter for physics so don't consider them
93 if ( m_ignore_masked_cells && std::abs(cell->e()) < 0.1 ) continue; //Fixme: use provenance
94
95 Identifier id = cell->ID();
96 if (m_ignore_front_innerwheel_cells && m_calo_id->is_em_endcap_inner(id) && m_calo_id->sampling(id) == 1) continue; // Front inner wheel cells are ignored
97
98 // saturated Qfactor ? Tight cuts.
99 if ( cell->quality()>=m_SaturatedCellQualityCut &&
100 std::abs(cell->e()) > m_SaturatedCellEnergyTightCut )
101 {
102 bool sideA = cell->eta() > 0.;
103 if ( m_calo_id->is_em_barrel(id) )
104 {
105 if ( sideA ) { NsaturatedTightCutBarrelA++; }
106 else { NsaturatedTightCutBarrelC++; }
107 }
108 else if ( m_calo_id->is_em_endcap(id) )
109 {
110 if ( sideA ) { NsaturatedTightCutEMECA++; }
111 else { NsaturatedTightCutEMECC++; }
112 }
113 }
114
115
116 // only LAr EM for bad FEBs
117 if ( m_calo_id->is_em(id) )
118 {
119 // get FEB ID and channel number
120 HWIdentifier hwid = cabling->createSignalChannelID(id);
121 HWIdentifier febid = m_onlineID->feb_Id(hwid);
122 unsigned int FEBindex = febid.get_identifier32().get_compact();
123 unsigned int channel = m_onlineID->channel(hwid);
124 FEBStats[FEBindex].addBadChannel(channel);
125 }
126
127 if (doHVline) {
128 //HVline, in all calos
129 std::vector<HWIdentifier> hvlines;
130 m_hvMapTool->GetHVLines(id, cddm,hvlines);
131 for (unsigned int i=0; i<hvlines.size(); ++i) {
132 auto& stats = HVStats[hvlines[i]];
133 stats.noisy += 1;
134 stats.sharedNoisy += static_cast<uint32_t>(hvlines.size());
135 }
136 }
137 }
138
139 // Store the Saturated flag per partition
140 uint8_t SatTightPartitions = 0;
141 if ( NsaturatedTightCutBarrelA >= m_SaturatedCellTightCut ) SatTightPartitions |= LArNoisyROSummary::EMBAMask;
142 if ( NsaturatedTightCutBarrelC >= m_SaturatedCellTightCut ) SatTightPartitions |= LArNoisyROSummary::EMBCMask;
143 if ( NsaturatedTightCutEMECA >= m_SaturatedCellTightCut ) SatTightPartitions |= LArNoisyROSummary::EMECAMask;
144 if ( NsaturatedTightCutEMECC >= m_SaturatedCellTightCut ) SatTightPartitions |= LArNoisyROSummary::EMECCMask;
145 bool badSaturatedTightCut = (SatTightPartitions != 0);
146 if ( badSaturatedTightCut ) noisyRO-> SetSatTightFlaggedPartitions(SatTightPartitions);
147
148 // loop on all FEBs and check whether FEB can be declared as bad for the different type of flags:
149 // regular noise burst, weighted noise burst, MNB tight and loose
150 for (auto& it : FEBStats) {
151 ATH_MSG_VERBOSE(" candidate FEB " << it.first << " with " << it.second.badChannels() << " bad channels");
152 if ( it.second.badChannels() > m_BadChanPerFEB ) {
153 noisyRO->add_noisy_feb(HWIdentifier(it.first));
154 }
155
156 // Loose MNBs
157 if ( it.second.badChannels() > m_MNBLooseCut ){
158 noisyRO->add_MNBLoose_feb(HWIdentifier(it.first));
159 ATH_MSG_DEBUG("Loose bad FEB " << it.first << " " << m_onlineID->channel_name(HWIdentifier(it.first)) << " with " << it.second.badChannels() << " bad channels");
160 // Tight_PsVeto MNBs
161 if ( it.second.badChannels() > m_MNBTight_PsVetoCut[0] ){
162 unsigned int associatedPSFEB = 0;
163 auto assoc_it = m_mapPSFEB.find(it.first);
164 if (assoc_it != m_mapPSFEB.end()) {
165 associatedPSFEB = assoc_it->second;
166 }
167 if (associatedPSFEB != 0){ // Check if a PS FEB is associated (TRUE only for EMB FEBs)
168 if (FEBStats.count(associatedPSFEB) == 0) noisyRO->add_MNBTight_PsVeto_feb(HWIdentifier(it.first));
169 else if (FEBStats[associatedPSFEB].badChannels() < m_MNBTight_PsVetoCut[1]) noisyRO->add_MNBTight_PsVeto_feb(HWIdentifier(it.first));
170 }
171 }
172 // Tight MNBs
173 if ( it.second.badChannels() > m_MNBTightCut ){
174 noisyRO->add_MNBTight_feb(HWIdentifier(it.first));
175 }
176 }
177
178 }//end loop over m_FEBats
179
180
181 // Count noisy FEB per partition EMEC-EMB - Simple and weighted quantities
182 unsigned int NBadFEBEMECA = 0; unsigned int NBadFEBEMECA_W = 0;
183 unsigned int NBadFEBEMECC = 0; unsigned int NBadFEBEMECC_W = 0;
184 unsigned int NBadFEBEMBA = 0; unsigned int NBadFEBEMBA_W = 0;
185 unsigned int NBadFEBEMBC = 0; unsigned int NBadFEBEMBC_W = 0;
186
187 const std::vector<HWIdentifier>& badfebs = noisyRO->get_noisy_febs();
188
189 //for ( std::vector<HWIdentifier>::const_iterator febit = badfebs.begin();
190 // febit != badfebs.end(); febit++ )
191 for (const HWIdentifier& febid : badfebs)
192 {
193 // first channel of FEB, as safety since FEBid seem to be the Id of the
194 // first channel (no guarantee?)
195 HWIdentifier chanID = m_onlineID->channel_Id(febid,0);
196
197 int weight = 1;
198 // If the FEB is known to be subject to noise burst (list defiend as property)
199 // give a weight 2
200 const unsigned int int_id = febid.get_identifier32().get_compact();
201 if (knownBadFEBs->find(int_id)!=knownBadFEBs->end()) weight=2;
202
203 if ( m_onlineID->isEMBchannel(chanID) )
204 {
205 if ( m_onlineID->pos_neg(chanID) == 1 ){
206 NBadFEBEMBA_W = NBadFEBEMBA_W + weight;
207 NBadFEBEMBA++;
208 }
209 else{
210 NBadFEBEMBC_W = NBadFEBEMBC_W + weight;
211 NBadFEBEMBC++;
212 }
213 }
214 else if ( m_onlineID->isEMECchannel(chanID) )
215 {
216 if ( m_onlineID->pos_neg(chanID) == 1 ){
217 NBadFEBEMECA_W = NBadFEBEMECA_W + weight;
218 NBadFEBEMECA++;
219 }
220 else{
221 NBadFEBEMECC_W = NBadFEBEMECC_W + weight;
222 NBadFEBEMECC++;
223 }
224 }
225 }
226
227 uint8_t BadFEBPartitions = 0;
228 if ( NBadFEBEMBA > m_MinBadFEB ) BadFEBPartitions |= LArNoisyROSummary::EMBAMask;
229 if ( NBadFEBEMBC > m_MinBadFEB ) BadFEBPartitions |= LArNoisyROSummary::EMBCMask;
230 if ( NBadFEBEMECA > m_MinBadFEB ) BadFEBPartitions |= LArNoisyROSummary::EMECAMask;
231 if ( NBadFEBEMECC > m_MinBadFEB ) BadFEBPartitions |= LArNoisyROSummary::EMECCMask;
232 if ( BadFEBPartitions != 0 ) noisyRO-> SetBadFEBFlaggedPartitions(BadFEBPartitions);
233
234 uint8_t BadFEBPartitions_W = 0;
235 if ( NBadFEBEMBA_W > m_MinBadFEB ) BadFEBPartitions_W |= LArNoisyROSummary::EMBAMask;
236 if ( NBadFEBEMBC_W > m_MinBadFEB ) BadFEBPartitions_W |= LArNoisyROSummary::EMBCMask;
237 if ( NBadFEBEMECA_W > m_MinBadFEB ) BadFEBPartitions_W |= LArNoisyROSummary::EMECAMask;
238 if ( NBadFEBEMECC_W > m_MinBadFEB ) BadFEBPartitions_W |= LArNoisyROSummary::EMECCMask;
239 if ( BadFEBPartitions_W != 0 ) noisyRO-> SetBadFEB_WFlaggedPartitions(BadFEBPartitions_W);
240
241
242
243 //Check for Mini Noise Bursts:
244 uint8_t MNBTightPartition=0;
245 uint8_t MNBTight_PsVetoPartition=0;
246 uint8_t MNBLoosePartition=0;
247
248 std::array<unsigned,5> nTightMNBFEBSperPartition{};
249 std::array<unsigned,5> nTight_PsVetoMNBFEBSperPartition{};
250 std::array<unsigned,5> nLooseMNBFEBSperPartition{};
251 for (HWIdentifier febid: *knownMNBFEBs) { //Loop over known MNB FEBs
252 auto statIt=FEBStats.find(febid.get_identifier32().get_compact());
253 if (statIt!=FEBStats.end()) {
254 if (statIt->second.badChannels()>=m_MNBLooseCut) {
255 (nLooseMNBFEBSperPartition[partitionNumber(febid)])++;
256 // Tight_PsVeto MNBs
257 if ( statIt->second.badChannels() > m_MNBTight_PsVetoCut[0] ){
258 auto found = m_mapPSFEB.find(statIt->first);
259 if (found != m_mapPSFEB.end()){
260 if (unsigned int associatedPSFEB = found->second; associatedPSFEB != 0){
261 if (FEBStats.count(associatedPSFEB) == 0) (nTight_PsVetoMNBFEBSperPartition[partitionNumber(febid)])++;
262 else if (FEBStats[associatedPSFEB].badChannels() < m_MNBTight_PsVetoCut[1]) (nTight_PsVetoMNBFEBSperPartition[partitionNumber(febid)])++;
263 }
264 }
265 }
266 // Tight MNBs
267 if (statIt->second.badChannels()>=m_MNBTightCut)
268 (nTightMNBFEBSperPartition[partitionNumber(febid)])++;
269 }
270 }//End FEB in list of bad-Q FEBs
271 }//end loop over known MNB Febs
272
273
274 for (unsigned iP=0;iP<4;++iP) {
275 ATH_MSG_DEBUG( "Partition " << iP << ": Found " << nLooseMNBFEBSperPartition[iP] << " MNB FEBs with more than " << m_MNBLooseCut << " bad-Q channels" );
276 ATH_MSG_DEBUG( "Partition " << iP << ": Found " << nTightMNBFEBSperPartition[iP] << " MNB FEBs with more than " << m_MNBTightCut << " bad-Q channels" );
277 if (nLooseMNBFEBSperPartition[iP]>0) MNBLoosePartition |= m_partitionMask[iP];
278 if (nTightMNBFEBSperPartition[iP]>0) MNBTightPartition |= m_partitionMask[iP];
279 if (nTight_PsVetoMNBFEBSperPartition[iP]>0) MNBTight_PsVetoPartition |= m_partitionMask[iP];
280 }// end loop over partitions
281
282
283 noisyRO->SetMNBTightFlaggedPartitions(MNBTightPartition);
284 noisyRO->SetMNBTight_PsVetoFlaggedPartitions(MNBTight_PsVetoPartition);
285 noisyRO->SetMNBLooseFlaggedPartitions(MNBLoosePartition);
286
287 if(!hvid || !nCellsperLine ) return noisyRO; // do not have HVcells map
288
289 // Count noisy HVlines per partition
290 float NBadHVEMECA = 0;
291 float NBadHVEMECC = 0;
292 float NBadHVEMBA = 0;
293 float NBadHVEMBC = 0;
294 float NBadHVHECA = 0;
295 float NBadHVHECC = 0;
296 float NBadHVFCALA = 0;
297 float NBadHVFCALC = 0;
298 // loop over HVlines, to check if they are qualified as noisy
299 for ( HVlinesStatMap::const_iterator it = HVStats.begin(); it != HVStats.end(); ++it ) {
300 ATH_MSG_DEBUG(ctx.eventID().event_number()<<" candidate HVline " << it->first << " with " << it->second.noisy << " bad channels, out of "<<nCellsperLine->HVNcell(HWIdentifier(it->first))<<" channels");
301 short nCells = nCellsperLine->HVNcell(it->first);
302 if ( it->second.noisy >= m_BadChanFracPerHVline * nCells && nCells >= static_cast<short>(m_connChanPerHVline)) {
303 HWIdentifier hwd(it->first);
304 noisyRO->add_noisy_hvline(hwd);
305 const std::vector<HWIdentifier> elecVec = hvid->getLArElectrodeIDvec(hwd);
306 int side = m_elecID->zside(elecVec[0]);
307 int part = m_elecID->detector(elecVec[0]);
308 const float w = float(it->second.noisy) / it->second.sharedNoisy;
309 switch(side) {
310 case 1: { ATH_MSG_DEBUG("Elec. side: "<<side);
311 switch(part){
312 case 0: case 1:{NBadHVEMBC += w; break;}
313 case 2: case 3:{NBadHVEMECC += w; break;}
314 case 4: {NBadHVHECC += w; break;}
315 case 5: {NBadHVFCALC += w; break;}
316 default: {ATH_MSG_WARNING("Wrong HV line detector "<<part); break;}
317 };
318 break;
319 }
320 case 0: { switch(part){
321 case 0: case 1:{NBadHVEMBA += w; break;}
322 case 2: case 3:{NBadHVEMECA += w; break;}
323 case 4: {NBadHVHECA += w; break;}
324 case 5: {NBadHVFCALA += w; break;}
325 default: {ATH_MSG_WARNING("Wrong HV line detector "<<part); break;}
326 };
327 break;
328 }
329 }
330 }// HVline is noisy
331 }// all hvlines
332
333 uint8_t BadHVPartitions = 0;
334 if ( NBadHVEMBA >= m_MinBadHV ) BadHVPartitions |= LArNoisyROSummary::EMBAMask;
335 if ( NBadHVEMBC >= m_MinBadHV ) BadHVPartitions |= LArNoisyROSummary::EMBCMask;
336 if ( NBadHVEMECA >= m_MinBadHV ) BadHVPartitions |= LArNoisyROSummary::EMECAMask;
337 if ( NBadHVEMECC >= m_MinBadHV ) BadHVPartitions |= LArNoisyROSummary::EMECCMask;
338 if ( NBadHVHECA >= m_MinBadHV ) BadHVPartitions |= LArNoisyROSummary::HECAMask;
339 if ( NBadHVHECC >= m_MinBadHV ) BadHVPartitions |= LArNoisyROSummary::HECCMask;
340 if ( NBadHVFCALA >= m_MinBadHV ) BadHVPartitions |= LArNoisyROSummary::FCALAMask;
341 if ( NBadHVFCALC >= m_MinBadHV ) BadHVPartitions |= LArNoisyROSummary::FCALCMask;
342
343 if ( BadHVPartitions != 0 ) noisyRO-> SetBadHVlinesPartitions(BadHVPartitions);
344
345 return noisyRO;
346}
347
348
349
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
Container class for CaloCell.
Data object for each calorimeter readout cell.
Definition CaloCell.h:57
This class provides the client interface for accessing the detector description information common to...
value_type get_compact() const
Get the compact id.
Identifier32 get_identifier32() const
Get the 32-bit version Identifier, will be invalid if >32 bits needed.
const std::vector< HWIdentifier > & getLArElectrodeIDvec(HWIdentifier &hvlineId) const
Return a vector of LArElectrodeID corresponding to a given LArHVLineID.
short HVNcell(const HWIdentifier &chid) const
Definition LArHVNMap.cxx:18
Gaudi::Property< unsigned int > m_MNBLooseCut
virtual std::unique_ptr< LArNoisyROSummary > process(const EventContext &, const CaloCellContainer *, const std::set< unsigned int > *, const std::vector< HWIdentifier > *, const LArHVNMap *, const CaloDetDescrManager *, const LArHVIdMapping *) const
Gaudi::Property< unsigned int > m_connChanPerHVline
Gaudi::Property< unsigned int > m_SaturatedCellTightCut
virtual StatusCode initialize()
Gaudi::Property< std::vector< unsigned int > > m_MNBTight_PsVetoCut
Gaudi::Property< float > m_SaturatedCellEnergyTightCut
size_t partitionNumber(const HWIdentifier) const
Gaudi::Property< bool > m_ignore_front_innerwheel_cells
ToolHandle< ILArHVMapTool > m_hvMapTool
const LArElectrodeID * m_elecID
const LArOnlineID * m_onlineID
std::unordered_map< unsigned int, FEBEvtStat > FEBEvtStatMap
Gaudi::Property< bool > m_doHVline
std::unordered_map< HWIdentifier, HVlinesStatMapValue > HVlinesStatMap
std::array< uint8_t, 4 > m_partitionMask
const CaloCell_ID * m_calo_id
Gaudi::Property< unsigned int > m_BadChanPerFEB
SG::ReadCondHandleKey< LArOnOffIdMapping > m_cablingKey
std::unordered_map< unsigned int, unsigned int > m_mapPSFEB
Gaudi::Property< bool > m_ignore_masked_cells
Gaudi::Property< unsigned int > m_MinBadFEB
Gaudi::Property< unsigned int > m_MNBTightCut
Gaudi::Property< float > m_BadChanFracPerHVline
Gaudi::Property< unsigned int > m_CellQualityCut
Gaudi::Property< unsigned int > m_SaturatedCellQualityCut
Gaudi::Property< unsigned int > m_MinBadHV