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 if(HVStats.contains(hvlines[i])) HVStats[hvlines[i]] += 1; else HVStats[hvlines[i]]=1;
133 }
134 }
135
136 }
137
138 // Store the Saturated flag per partition
139 uint8_t SatTightPartitions = 0;
140 if ( NsaturatedTightCutBarrelA >= m_SaturatedCellTightCut ) SatTightPartitions |= LArNoisyROSummary::EMBAMask;
141 if ( NsaturatedTightCutBarrelC >= m_SaturatedCellTightCut ) SatTightPartitions |= LArNoisyROSummary::EMBCMask;
142 if ( NsaturatedTightCutEMECA >= m_SaturatedCellTightCut ) SatTightPartitions |= LArNoisyROSummary::EMECAMask;
143 if ( NsaturatedTightCutEMECC >= m_SaturatedCellTightCut ) SatTightPartitions |= LArNoisyROSummary::EMECCMask;
144 bool badSaturatedTightCut = (SatTightPartitions != 0);
145 if ( badSaturatedTightCut ) noisyRO-> SetSatTightFlaggedPartitions(SatTightPartitions);
146
147 // loop on all FEBs and check whether FEB can be declared as bad for the different type of flags:
148 // regular noise burst, weighted noise burst, MNB tight and loose
149 for (auto& it : FEBStats) {
150 ATH_MSG_VERBOSE(" candidate FEB " << it.first << " with " << it.second.badChannels() << " bad channels");
151 if ( it.second.badChannels() > m_BadChanPerFEB ) {
152 noisyRO->add_noisy_feb(HWIdentifier(it.first));
153 }
154
155 // Loose MNBs
156 if ( it.second.badChannels() > m_MNBLooseCut ){
157 noisyRO->add_MNBLoose_feb(HWIdentifier(it.first));
158 ATH_MSG_DEBUG("Loose bad FEB " << it.first << " " << m_onlineID->channel_name(HWIdentifier(it.first)) << " with " << it.second.badChannels() << " bad channels");
159 // Tight_PsVeto MNBs
160 if ( it.second.badChannels() > m_MNBTight_PsVetoCut[0] ){
161 unsigned int associatedPSFEB = 0;
162 auto assoc_it = m_mapPSFEB.find(it.first);
163 if (assoc_it != m_mapPSFEB.end()) {
164 associatedPSFEB = assoc_it->second;
165 }
166 if (associatedPSFEB != 0){ // Check if a PS FEB is associated (TRUE only for EMB FEBs)
167 if (FEBStats.count(associatedPSFEB) == 0) noisyRO->add_MNBTight_PsVeto_feb(HWIdentifier(it.first));
168 else if (FEBStats[associatedPSFEB].badChannels() < m_MNBTight_PsVetoCut[1]) noisyRO->add_MNBTight_PsVeto_feb(HWIdentifier(it.first));
169 }
170 }
171 // Tight MNBs
172 if ( it.second.badChannels() > m_MNBTightCut ){
173 noisyRO->add_MNBTight_feb(HWIdentifier(it.first));
174 }
175 }
176
177 }//end loop over m_FEBats
178
179
180 // Count noisy FEB per partition EMEC-EMB - Simple and weighted quantities
181 unsigned int NBadFEBEMECA = 0; unsigned int NBadFEBEMECA_W = 0;
182 unsigned int NBadFEBEMECC = 0; unsigned int NBadFEBEMECC_W = 0;
183 unsigned int NBadFEBEMBA = 0; unsigned int NBadFEBEMBA_W = 0;
184 unsigned int NBadFEBEMBC = 0; unsigned int NBadFEBEMBC_W = 0;
185
186 const std::vector<HWIdentifier>& badfebs = noisyRO->get_noisy_febs();
187
188 //for ( std::vector<HWIdentifier>::const_iterator febit = badfebs.begin();
189 // febit != badfebs.end(); febit++ )
190 for (const HWIdentifier& febid : badfebs)
191 {
192 // first channel of FEB, as safety since FEBid seem to be the Id of the
193 // first channel (no guarantee?)
194 HWIdentifier chanID = m_onlineID->channel_Id(febid,0);
195
196 int weight = 1;
197 // If the FEB is known to be subject to noise burst (list defiend as property)
198 // give a weight 2
199 const unsigned int int_id = febid.get_identifier32().get_compact();
200 if (knownBadFEBs->find(int_id)!=knownBadFEBs->end()) weight=2;
201
202 if ( m_onlineID->isEMBchannel(chanID) )
203 {
204 if ( m_onlineID->pos_neg(chanID) == 1 ){
205 NBadFEBEMBA_W = NBadFEBEMBA_W + weight;
206 NBadFEBEMBA++;
207 }
208 else{
209 NBadFEBEMBC_W = NBadFEBEMBC_W + weight;
210 NBadFEBEMBC++;
211 }
212 }
213 else if ( m_onlineID->isEMECchannel(chanID) )
214 {
215 if ( m_onlineID->pos_neg(chanID) == 1 ){
216 NBadFEBEMECA_W = NBadFEBEMECA_W + weight;
217 NBadFEBEMECA++;
218 }
219 else{
220 NBadFEBEMECC_W = NBadFEBEMECC_W + weight;
221 NBadFEBEMECC++;
222 }
223 }
224 }
225
226 uint8_t BadFEBPartitions = 0;
227 if ( NBadFEBEMBA > m_MinBadFEB ) BadFEBPartitions |= LArNoisyROSummary::EMBAMask;
228 if ( NBadFEBEMBC > m_MinBadFEB ) BadFEBPartitions |= LArNoisyROSummary::EMBCMask;
229 if ( NBadFEBEMECA > m_MinBadFEB ) BadFEBPartitions |= LArNoisyROSummary::EMECAMask;
230 if ( NBadFEBEMECC > m_MinBadFEB ) BadFEBPartitions |= LArNoisyROSummary::EMECCMask;
231 if ( BadFEBPartitions != 0 ) noisyRO-> SetBadFEBFlaggedPartitions(BadFEBPartitions);
232
233 uint8_t BadFEBPartitions_W = 0;
234 if ( NBadFEBEMBA_W > m_MinBadFEB ) BadFEBPartitions_W |= LArNoisyROSummary::EMBAMask;
235 if ( NBadFEBEMBC_W > m_MinBadFEB ) BadFEBPartitions_W |= LArNoisyROSummary::EMBCMask;
236 if ( NBadFEBEMECA_W > m_MinBadFEB ) BadFEBPartitions_W |= LArNoisyROSummary::EMECAMask;
237 if ( NBadFEBEMECC_W > m_MinBadFEB ) BadFEBPartitions_W |= LArNoisyROSummary::EMECCMask;
238 if ( BadFEBPartitions_W != 0 ) noisyRO-> SetBadFEB_WFlaggedPartitions(BadFEBPartitions_W);
239
240
241
242 //Check for Mini Noise Bursts:
243 uint8_t MNBTightPartition=0;
244 uint8_t MNBTight_PsVetoPartition=0;
245 uint8_t MNBLoosePartition=0;
246
247 std::array<unsigned,5> nTightMNBFEBSperPartition{};
248 std::array<unsigned,5> nTight_PsVetoMNBFEBSperPartition{};
249 std::array<unsigned,5> nLooseMNBFEBSperPartition{};
250 for (HWIdentifier febid: *knownMNBFEBs) { //Loop over known MNB FEBs
251 auto statIt=FEBStats.find(febid.get_identifier32().get_compact());
252 if (statIt!=FEBStats.end()) {
253 if (statIt->second.badChannels()>=m_MNBLooseCut) {
254 (nLooseMNBFEBSperPartition[partitionNumber(febid)])++;
255 // Tight_PsVeto MNBs
256 if ( statIt->second.badChannels() > m_MNBTight_PsVetoCut[0] ){
257 auto found = m_mapPSFEB.find(statIt->first);
258 if (found != m_mapPSFEB.end()){
259 if (unsigned int associatedPSFEB = found->second; associatedPSFEB != 0){
260 if (FEBStats.count(associatedPSFEB) == 0) (nTight_PsVetoMNBFEBSperPartition[partitionNumber(febid)])++;
261 else if (FEBStats[associatedPSFEB].badChannels() < m_MNBTight_PsVetoCut[1]) (nTight_PsVetoMNBFEBSperPartition[partitionNumber(febid)])++;
262 }
263 }
264 }
265 // Tight MNBs
266 if (statIt->second.badChannels()>=m_MNBTightCut)
267 (nTightMNBFEBSperPartition[partitionNumber(febid)])++;
268 }
269 }//End FEB in list of bad-Q FEBs
270 }//end loop over known MNB Febs
271
272
273 for (unsigned iP=0;iP<4;++iP) {
274 ATH_MSG_DEBUG( "Partition " << iP << ": Found " << nLooseMNBFEBSperPartition[iP] << " MNB FEBs with more than " << m_MNBLooseCut << " bad-Q channels" );
275 ATH_MSG_DEBUG( "Partition " << iP << ": Found " << nTightMNBFEBSperPartition[iP] << " MNB FEBs with more than " << m_MNBTightCut << " bad-Q channels" );
276 if (nLooseMNBFEBSperPartition[iP]>0) MNBLoosePartition |= m_partitionMask[iP];
277 if (nTightMNBFEBSperPartition[iP]>0) MNBTightPartition |= m_partitionMask[iP];
278 if (nTight_PsVetoMNBFEBSperPartition[iP]>0) MNBTight_PsVetoPartition |= m_partitionMask[iP];
279 }// end loop over partitions
280
281
282 noisyRO->SetMNBTightFlaggedPartitions(MNBTightPartition);
283 noisyRO->SetMNBTight_PsVetoFlaggedPartitions(MNBTight_PsVetoPartition);
284 noisyRO->SetMNBLooseFlaggedPartitions(MNBLoosePartition);
285
286 if(!hvid || !nCellsperLine ) return noisyRO; // do not have HVcells map
287
288 // Count noisy HVlines per partition
289 unsigned int NBadHVEMECA = 0;
290 unsigned int NBadHVEMECC = 0;
291 unsigned int NBadHVEMBA = 0;
292 unsigned int NBadHVEMBC = 0;
293 unsigned int NBadHVHECA = 0;
294 unsigned int NBadHVHECC = 0;
295 unsigned int NBadHVFCALA = 0;
296 unsigned int NBadHVFCALC = 0;
297
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 << " bad channels, out of "<<nCellsperLine->HVNcell(HWIdentifier(it->first))<<" channels");
301 if ( it->second >= m_BadChanFracPerHVline * nCellsperLine->HVNcell(it->first) ) {
302 HWIdentifier hwd(it->first);
303 noisyRO->add_noisy_hvline(hwd);
304 const std::vector<HWIdentifier> elecVec = hvid->getLArElectrodeIDvec(hwd);
305 int side = m_elecID->zside(elecVec[0]);
306 int part = m_elecID->detector(elecVec[0]);
307 switch(side) {
308 case 1: { ATH_MSG_DEBUG("Elec. side: "<<side);
309 switch(part){
310 case 0: case 1:{NBadHVEMBC += 1; break;}
311 case 2: case 3:{NBadHVEMECC += 1; break;}
312 case 4: {NBadHVHECC += 1; break;}
313 case 5: {NBadHVFCALC += 1; break;}
314 default: {ATH_MSG_WARNING("Wrong HV line detector "<<part); break;}
315 };
316 break;
317 }
318 case 0: { switch(part){
319 case 0: case 1:{NBadHVEMBA += 1; break;}
320 case 2: case 3:{NBadHVEMECA += 1; break;}
321 case 4: {NBadHVHECA += 1; break;}
322 case 5: {NBadHVFCALA += 1; break;}
323 default: {ATH_MSG_WARNING("Wrong HV line detector "<<part); break;}
324 };
325 break;
326 }
327 }
328 }// HVline is noisy
329 }// all hvlines
330
331 uint8_t BadHVPartitions = 0;
332 if ( NBadHVEMBA >= m_MinBadHV ) BadHVPartitions |= LArNoisyROSummary::EMBAMask;
333 if ( NBadHVEMBC >= m_MinBadHV ) BadHVPartitions |= LArNoisyROSummary::EMBCMask;
334 if ( NBadHVEMECA >= m_MinBadHV ) BadHVPartitions |= LArNoisyROSummary::EMECAMask;
335 if ( NBadHVEMECC >= m_MinBadHV ) BadHVPartitions |= LArNoisyROSummary::EMECCMask;
336 if ( NBadHVHECA >= m_MinBadHV ) BadHVPartitions |= LArNoisyROSummary::HECAMask;
337 if ( NBadHVHECC >= m_MinBadHV ) BadHVPartitions |= LArNoisyROSummary::HECCMask;
338 if ( NBadHVFCALA >= m_MinBadHV ) BadHVPartitions |= LArNoisyROSummary::FCALAMask;
339 if ( NBadHVFCALC >= m_MinBadHV ) BadHVPartitions |= LArNoisyROSummary::FCALCMask;
340
341 if ( BadHVPartitions != 0 ) noisyRO-> SetBadHVlinesPartitions(BadHVPartitions);
342
343 return noisyRO;
344}
345
346
347
#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_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, unsigned int > 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