ATLAS Offline Software
Loading...
Searching...
No Matches
LArCalibPatchingAlg.icc
Go to the documentation of this file.
1//Dear emacs, this is -*-c++-*-
2/*
3 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
4*/
5
6#include <tuple>
7
8template<class CONDITIONSCONTAINER>
9LArCalibPatchingAlg<CONDITIONSCONTAINER>::LArCalibPatchingAlg (const std::string& name, ISvcLocator* pSvcLocator) :
10 AthAlgorithm(name,pSvcLocator),
11 m_onlineHelper(0),
12 m_caloId(0),
13 m_contIn(0),
14 m_contOut(0),
15 m_patchMethod(PhiAverage) { }
16
17
18template<class CONDITIONSCONTAINER>
19StatusCode LArCalibPatchingAlg<CONDITIONSCONTAINER>::initialize() {
20
21 ATH_CHECK( m_BCKey.initialize() );
22 ATH_CHECK( m_cablingKey.initialize() );
23 ATH_CHECK( m_CLKey.initialize() );
24
25
26 if(m_patchMethodProp=="FEBNeighbor") {
27 m_patchMethod=FEBNeighbor;
28 return StatusCode::SUCCESS;
29 }
30 else if (m_patchMethodProp=="PhiNeighbor") {
31 m_patchMethod=PhiNeighbor;
32 return StatusCode::SUCCESS;
33 }
34 else if (m_patchMethodProp=="PhiAverage") {
35 if (typeid(CONDITIONSCONTAINER)==typeid(LArAutoCorrComplete)) {
36 ATH_MSG_ERROR ( "PhiAverage not implemented for LArAutoCorrComlete."
37 << "Please choose other patching strategy" );
38 return StatusCode::FAILURE;
39 }
40 m_patchMethod=PhiAverage;
41 return StatusCode::SUCCESS;
42 }
43 else if (m_patchMethodProp=="FEBAverage") {
44 if (typeid(CONDITIONSCONTAINER)==typeid(LArCaliWaveContainer)) {
45 ATH_MSG_ERROR ( "FEBAverage not implemented for CaliWaveContainer."
46 << "Please choose other patching strategy" );
47 return StatusCode::FAILURE;
48 }
49 m_patchMethod=FEBAverage;
50 return StatusCode::SUCCESS;
51 } else if (m_patchMethodProp=="SetZero") {
52 if (typeid(CONDITIONSCONTAINER)==typeid(LArCaliWaveContainer)) {
53 ATH_MSG_ERROR ( "SetZero not implemented for CaliWaveContainer."
54 << "Please choose other patching strategy" );
55 return StatusCode::FAILURE;
56 }
57 m_patchMethod=SetZero;
58 return StatusCode::SUCCESS;
59 }
60
61 ATH_MSG_ERROR ( "Unknown patching method: " << m_patchMethodProp );
62 ATH_MSG_ERROR ( "Allowed values: [Empty, FEBNeighbor, PhiNeighbor, PhiAverage, SetZero]" );
63
64 return StatusCode::FAILURE;
65}
66
67template<class CONDITIONSCONTAINER>
68StatusCode LArCalibPatchingAlg<CONDITIONSCONTAINER>::stop() {
69 ATH_MSG_INFO ( "Entering LArCalibPatchingAlg" );
70 if(m_isSC) {
71 ATH_CHECK( detStore()->retrieve(m_onlineHelper, "LArOnline_SuperCellID") );
72 ATH_CHECK( detStore()->retrieve(m_caloId, "CaloCell_SuperCell_ID") );
73 } else {
74 ATH_CHECK( detStore()->retrieve(m_onlineHelper, "LArOnlineID") );
75 ATH_CHECK( detStore()->retrieve(m_caloId, "CaloCell_ID") );
76 }
77
78 if(m_isSC) m_bcMask.setSC();
79 ATH_CHECK(m_bcMask.buildBitMask(m_problemsToPatch,msg()));
80
81 const EventContext& ctx = Gaudi::Hive::currentContext();
82
83 SG::ReadCondHandle<LArBadChannelCont> readHandle{m_BCKey, ctx};
84 const LArBadChannelCont *bcCont {*readHandle};
85 if(!bcCont) {
86 ATH_MSG_ERROR( "Do not have Bad chan container !!!" );
87 return StatusCode::FAILURE;
88 }
89
90 SG::ReadCondHandle<LArOnOffIdMapping> cablingHdl{m_cablingKey, ctx};
91 const LArOnOffIdMapping* cabling = *cablingHdl;
92 if(!cabling) {
93 ATH_MSG_ERROR( "Do not have OnOff Id mapping !!!" );
94 return StatusCode::FAILURE;
95 }
96
97 SG::ReadCondHandle<LArCalibLineMapping> clHdl{m_CLKey, ctx};
98 const LArCalibLineMapping *clCont {*clHdl};
99 if(!clCont) {
100 ATH_MSG_ERROR( "Do not have calib line mapping !!!" );
101 return StatusCode::FAILURE;
102 }
103
104 if (m_newContainerKey.size()) {
105 //New container key give -> different containers for reading and writing
106 ATH_CHECK( detStore()->retrieve(m_contIn,m_containerKey) ); //const-retrieve
107
108 m_contOut=new CONDITIONSCONTAINER();
109 m_contOut->setGroupingType((LArConditionsContainerBase::GroupingType)m_contIn->groupingType());
110 ATH_CHECK( m_contOut->initialize() );
111 ATH_CHECK( detStore()->record(m_contOut,m_newContainerKey) );
112 ATH_MSG_INFO ( "Loaded input container " << m_containerKey
113 << ", write to new container " << m_newContainerKey );
114 }
115 else { //Same container for reading and writing
116 if (m_unlock) {
117 ATH_CHECK( detStore()->retrieve(m_contIn,m_containerKey) ); //const-retrieve
118 m_contOut=const_cast<CONDITIONSCONTAINER*>(m_contIn);
119 }
120 else{
121 ATH_CHECK( detStore()->retrieve(m_contOut,m_containerKey) ); //non-const retrieve
122 m_contIn=const_cast<const CONDITIONSCONTAINER*>(m_contOut);
123 ATH_MSG_INFO ( "Work on container '" << m_containerKey << "'" );
124 }
125 }
126
127 LArBadChanBitPacking packing;
128 LArBadChanSCBitPacking scpacking;
129
130 unsigned maxgain;
131 if(m_isSC) maxgain=CaloGain::LARMEDIUMGAIN; else maxgain=CaloGain::LARNGAIN;
132 for (unsigned igain=CaloGain::LARHIGHGAIN;
133 igain<maxgain ; ++igain ) {
134 CONTIT it=m_contIn->begin(igain);
135 CONTIT it_e=m_contIn->end(igain);
136 for (;it!=it_e;it++) {
137 const HWIdentifier chid = it.channelId();
138 if (!cabling->isOnlineConnected(chid)) continue; //Don't care about disconnected channels
139 if (m_bcMask.cellShouldBeMasked(bcCont,chid)) {
140 const std::string bcType = m_isSC ? scpacking.stringStatus(bcCont->status(chid)) : packing.stringStatus(bcCont->status(chid));
141 ATH_MSG_INFO ( "Found problematic channel 0x" << MSG::hex << chid.get_identifier32().get_compact() << MSG::dec << " [" << bcType << "]"
142 <<" Gain:" << igain << " " << m_onlineHelper->channel_name(chid) << ". Trying to patch." );
143 if (patch(chid,igain, bcCont, cabling, clCont)) {
144 ATH_MSG_INFO ( "Sucessfully patched channel 0x" << MSG::hex << chid.get_identifier32().get_compact() << MSG::dec <<" Gain:" << igain );
145 } else {
146 ATH_MSG_WARNING ( "Failed to patch channel 0x" << MSG::hex << chid.get_identifier32().get_compact() << MSG::dec <<" Gain:" << igain );
147 }
148 }//end if channel is in bad-channel database
149 else
150 if (it->isEmpty()) { //check if data-object is empty (eg the default instance
151 ATH_MSG_ERROR ( "The channel 0x" << MSG::hex << chid.get_identifier32().get_compact() << MSG::dec
152 <<" Gain:" << igain << " " << m_onlineHelper->channel_name(chid)
153 << " has no calibration but is not (yet?) flagged in the bad-channel database" );
154 if (m_patchAllMissing) {
155 ATH_MSG_INFO ( "Will try to patch anyway." );
156 if (patch(chid,igain, bcCont, cabling, clCont)) {
157 ATH_MSG_INFO ( "Sucessfully patched channel 0x" << MSG::hex << chid.get_identifier32().get_compact() << MSG::dec <<" Gain:" << igain );
158 } else {
159 ATH_MSG_WARNING ( "Failed to patch channel 0x" << MSG::hex << chid.get_identifier32().get_compact() << MSG::dec <<" Gain:" << igain );
160 }
161 }//end if m_patchAllMissing
162 else
163 ATH_MSG_ERROR ( "Channel remains un-patched!" );
164 }//end if isEmpty
165 }//end loop over all channels
166 }//end loop over all gains
167
168 std::vector<unsigned> completedChans = m_contOut->completeCorrectionChannels();
169 if (completedChans.size()>0 && m_useCorrChannel) {
170 msg() << MSG::INFO << "Artificially inserted correction subsets in COOL channels";
171 for(size_t j=0;j<completedChans.size();++j)
172 msg() << MSG::INFO << " " << completedChans[j];
173 msg() << MSG::INFO << endmsg;
174 }
175
176
177 ATH_MSG_INFO ( "Done with LArCalibPatchingAlg" );
178 ATH_MSG_DEBUG ( detStore()->dump() );
179 return StatusCode::SUCCESS;
180}
181
182template<class CONDITIONSCONTAINER>
183bool LArCalibPatchingAlg<CONDITIONSCONTAINER>::patch(const HWIdentifier chid, const int gain, const LArBadChannelCont* bcCont, const LArOnOffIdMapping* cabling, const LArCalibLineMapping *clCont) {
184
185 if(m_doNotPatchCBs.size()>0) { // check if this channel is not on excluded CalibBoard
186 const std::vector<HWIdentifier>& cLids=clCont->calibSlotLine(chid);
187 for(unsigned cl=0; cl<cLids.size(); ++cl) {
188 const HWIdentifier calibModuleID = m_onlineHelper->calib_module_Id(cLids[cl]);
189 if (std::find(m_doNotPatchCBs.begin(),m_doNotPatchCBs.end(),calibModuleID.get_identifier32().get_compact()) != m_doNotPatchCBs.end()) { // we should not patch this channel
190 return false;
191 }
192 } // over CLs
193 }
194
195 if (m_patchMethod==FEBNeighbor){
196 const HWIdentifier febId=m_onlineHelper->feb_Id(chid);
197 const int febChan=m_onlineHelper->channel(chid);
198 HWIdentifier chid_patch(0);
199 if (febChan>0) {
200 //try lower channel
201 chid_patch=m_onlineHelper->channel_Id(febId, febChan-1);
202 if (cabling->isOnlineConnected(chid_patch) && bcCont->status(chid_patch).good()) {
203 const LArCondObj patch=m_contIn->get(chid_patch,gain); //Should be the const-get method
204 if (!patch.isEmpty()) {
205 StatusCode sc=m_contOut->insertCorrection(chid,patch,gain,m_useCorrChannel);
206 if (sc.isFailure())
207 ATH_MSG_ERROR ( "Failed to insert correction for channel 0x" << MSG::hex << chid.get_compact()
208 << MSG::dec <<", gain " << gain << "." );
209 else
210 ATH_MSG_INFO ( "Replaced channel 0x" << MSG::hex << chid.get_compact()
211 << " by it's left FEB neighbor 0x" << chid_patch.get_compact() << MSG::dec );
212 return true;
213 }
214 }//end if patch connected and good
215 }//end if febChan
216 if (febChan<(m_onlineHelper->channelInSlotMax(febId)-1)) {
217 chid_patch=m_onlineHelper->channel_Id(febId, febChan+1);
218 if (cabling->isOnlineConnected(chid_patch) && bcCont->status(chid_patch).good()) {
219 const LArCondObj patch=m_contIn->get(chid_patch,gain); //Should be the const-get method
220 if (!patch.isEmpty()) {
221 StatusCode sc=m_contOut->insertCorrection(chid,patch,gain,m_useCorrChannel);
222 if (sc.isFailure()) {
223 ATH_MSG_ERROR ( "Failed to insert correction for channel 0x" << MSG::hex << chid.get_compact()
224 << MSG::dec << ", gain " << gain << "." );
225 }
226 else {
227 ATH_MSG_INFO ( "Replaced channel 0x" << MSG::hex << chid.get_compact()
228 << " by it's right FEB neighbor 0x" << chid_patch.get_compact() << MSG::dec );
229 return true;
230 }
231 }//end if patch connected and good
232 }//end if chan<max
233 }
234 ATH_MSG_ERROR ( "None of the FEB neighbors is good!" );
235 return false;
236 } else if (m_patchMethod==PhiNeighbor) {
237 // (*m_log) << MSG::ERROR << "Patching Method 'Phi-neighbor' not yet implemented." << endmsg;
238 try {
239 const Identifier id=cabling->cnvToIdentifier(chid);
240 int eta, phi, phi_min, phi_max, phi_range;
241 Identifier regionID;
242 regionID=m_caloId->region_id(id);
243 eta = m_caloId->eta(id);
244 phi = m_caloId->phi(id);
245 phi_min =m_caloId->phi_min(regionID);
246 phi_max =m_caloId->phi_max(regionID);
247 phi_range=phi_max-phi_min+1;
248 if (eta==CaloCell_ID::NOT_VALID || phi==CaloCell_ID::NOT_VALID || phi_min==CaloCell_ID::NOT_VALID || phi_max==CaloCell_ID::NOT_VALID) {
249 ATH_MSG_ERROR ( "CaloCell_ID returned NOT_VALID for offline id 0x"<< std::hex << id.get_compact()
250 <<", online id 0x" << chid.get_compact() << std::dec );
251 return false;
252 }
253 ATH_MSG_VERBOSE ( "Problem channel has phi="<< phi << " eta=" << eta );
254 //Try both phi-neighbors
255 int phi_list[4]={phi-1,phi+1,phi-2,phi+2};
256 for (unsigned i=0;i<4;i++) {
257 int phi_patch=phi_list[i];
258 if (phi_patch<m_caloId->phi_min(regionID)) phi_patch=phi_patch+phi_range;
259 if (phi_patch>m_caloId->phi_max(regionID)) phi_patch=phi_patch-phi_range+phi_min;
260 ATH_MSG_VERBOSE ( "Iteration " << i << " Using cell with phi="
261 << phi_patch << " eta=" << eta );
262 //std::cout << "i=" << i << " Using cell with phi="
263 // << phi_patch << " eta=" << eta << std::endl;
264 Identifier patch_id=m_caloId->cell_id(regionID,eta,phi_patch);
265 HWIdentifier chid_patch=cabling->createSignalChannelID(patch_id);
266 if (bcCont->status(chid_patch).good()) {
267 const LArCondObj patch=m_contIn->get(chid_patch,gain);
268 if (!patch.isEmpty()) {
269 StatusCode sc=m_contOut->insertCorrection(chid,patch,gain,m_useCorrChannel);
270 if (sc.isFailure())
271 ATH_MSG_ERROR ( "Failed to insert correction for channel 0x" << MSG::hex << chid.get_compact()
272 << MSG::dec << ", gain " << gain << "." );
273 else
274 ATH_MSG_INFO ( "Replaced channel 0x" << MSG::hex << chid.get_compact()
275 << " by neighbor 0x" << chid_patch.get_compact() << MSG::dec << " (phi " << phi << " to " << phi_patch <<")" );
276 return true;
277 }//end if isEmtpy()
278 }//end if neighbor is good
279 }// end for loop
280 ATH_MSG_ERROR ( "All phi-neighbors of channel 0x" << MSG::hex << chid.get_compact() << MSG::dec
281 << " are either absent or bad." );
282 return false;
283 }catch(LArID_Exception& except) {
284 ATH_MSG_ERROR ( "LArID_Exception caught!" );
285 return false;
286 }
287 }
288 else if (m_patchMethod==PhiAverage) {
289 LArCondObj patch;
290 if (!getAverage(chid,gain,patch,bcCont,cabling)){
291 ATH_MSG_ERROR ( "Failed get phi-average!" );
292 return false;
293 } else {
294 ATH_MSG_DEBUG ( "Got a phi-average..." );
295 }
296 ATH_CHECK( m_contOut->insertCorrection(chid,patch,gain,m_useCorrChannel), false );
297 return true;
298 }
299 else if (m_patchMethod==FEBAverage) {
300 LArCondObj patch;
301 if (!getAverage(chid,gain,patch,bcCont, cabling, false)){
302 ATH_MSG_ERROR ( "Failed get FEB-average!" );
303 return false;
304 } else {
305 ATH_MSG_DEBUG ( "Got a FEB-average..." );
306 }
307 ATH_CHECK( m_contOut->insertCorrection(chid,patch,gain,m_useCorrChannel), false );
308 return true;
309 }
310 else if (m_patchMethod==SetZero) {
311 LArCondObj patch;
312 if (!setZero(chid, gain, patch)){
313 ATH_MSG_ERROR ( "Failed set Zero!" );
314 return false;
315 } else {
316 ATH_MSG_DEBUG ( "Set zero ..." );
317 }
318 ATH_CHECK( m_contOut->insertCorrection(chid,patch,gain,m_useCorrChannel), false );
319 return true;
320 }
321 else //failed...
322 ATH_MSG_ERROR ( "Unknown correction method." );
323 return false;
324}
325
326
327template<class CONDITIONSCONTAINER>
328std::vector<HWIdentifier>& LArCalibPatchingAlg<CONDITIONSCONTAINER>::getPhiRing(const HWIdentifier chid, const LArBadChannelCont* bcCont, const LArOnOffIdMapping* cabling, unsigned distance) {
329 if (distance==0) distance=1;
330 m_idList.clear();
331 try {
332 const Identifier id=cabling->cnvToIdentifier(chid);
333 int eta,phi, phi_min, phi_max;
334 Identifier regionID;
335 regionID=m_caloId->region_id(id);
336 eta = m_caloId->eta(id);
337 phi = m_caloId->phi(id);
338 phi_min =m_caloId->phi_min(regionID);
339 phi_max =m_caloId->phi_max(regionID);
340 ATH_MSG_VERBOSE ( "Assembling phi-ring for eta=" << eta << " phi=" << phi );
341 //std::cout << "Assembling phi-ring for eta=" << eta << " phi=" << phi << std::endl;
342 if (eta==CaloCell_ID::NOT_VALID || phi==CaloCell_ID::NOT_VALID || phi_min==CaloCell_ID::NOT_VALID || phi_max==CaloCell_ID::NOT_VALID) {
343 ATH_MSG_ERROR ( "CaloCell_ID returned NOT_VALID for offline id 0x"<< std::hex << id.get_compact()
344 <<", online id 0x" << chid.get_compact() << std::dec );
345 return m_idList;
346 }
347
348 if ((phi_max-phi_min)%distance) {
349 ATH_MSG_ERROR ( "Can't divide " << (phi_min-phi_max) << " by " << distance );
350 return m_idList;
351 }
352
353 int nSteps=(phi_max-phi_min)/distance;
354
355 for (int i=1;i<=nSteps;i++) {
356 int phi_patch=phi+i*distance;
357 if (phi_patch>phi_max) phi_patch=phi_patch-phi_max+phi_min-1;
358 ATH_MSG_VERBOSE ( "i=" << i << " Adding cell with phi="
359 << phi_patch << " eta=" << eta );
360 //std::cout << "i=" << i << " Adding cell with phi="
361 // << phi_patch << " eta=" << eta << std::endl;
362 Identifier patch_id=m_caloId->cell_id(regionID,eta,phi_patch);
363 HWIdentifier chid_patch=cabling->createSignalChannelID(patch_id);
364 if (bcCont->status(chid_patch).good()) {
365 m_idList.push_back(chid_patch);
366 }
367 else
368 ATH_MSG_VERBOSE ( "This cell is bad as well. Ignored." );
369 }//end loop over phi-steps
370
371 }catch(LArID_Exception& except) {
372 ATH_MSG_ERROR ( "LArID_Exception caught!" );
373 }
374 return m_idList;
375}
376
377template<class CONDITIONSCONTAINER>
378std::vector<HWIdentifier>& LArCalibPatchingAlg<CONDITIONSCONTAINER>::getFEBChans(const HWIdentifier chid, const LArBadChannelCont* bcCont) {
379 m_idList.clear();
380 HWIdentifier febid = m_onlineHelper->feb_Id(chid);
381 ATH_MSG_VERBOSE ( "Assembling list of channels for FEB=" << febid );
382 for (int i=0;i<128;++i) {
383 HWIdentifier fchan = m_onlineHelper->channel_Id(febid,i);
384 if(fchan == chid) continue;
385 ATH_MSG_VERBOSE ( " Adding channel =" << i );
386 if (bcCont->status(fchan).good()) {
387 m_idList.push_back(fchan);
388 } else {
389 ATH_MSG_VERBOSE ( "This channel is bad as well. Ignored." );
390 }
391 }//end loop over chans
392
393 return m_idList;
394}
395
396
397template<class CONDITIONSCONTAINER>
398bool LArCalibPatchingAlg<CONDITIONSCONTAINER>::getAverage(const HWIdentifier chid, const int gain, LArRampP1& patch, const LArBadChannelCont* bcCont, const LArOnOffIdMapping* cabling, bool isphi) {
399
400 std::vector<HWIdentifier>& symCells =
401 isphi ? getPhiRing(chid, bcCont, cabling) : getFEBChans(chid, bcCont);
402 if (symCells.empty()) {
403 ATH_MSG_ERROR ( "No symmetry cells found!" );
404 return false;
405 }
406 size_t s=m_contIn->get(symCells[0],gain).m_vRamp.size();
407 patch.m_vRamp.clear();
408 patch.m_vRamp.resize(s);
409 unsigned nCells=0;
410 for (HWIdentifier hwid : symCells) {
411 const LArRampP1& ramp=m_contIn->get(hwid,gain);
412 if (ramp.m_vRamp.size()==0) continue; //This one is empty...
413 if (ramp.m_vRamp.size()!=s) {
414 if(isphi) {
415 ATH_MSG_WARNING ("Cell with same phi but different size of ramp polynom found!" );
416 } else {
417 ATH_MSG_WARNING ("Cell with same FEB but different size of ramp polynom found!" );
418 }
419 continue;
420 }
421 msg() << MSG::DEBUG << "Adding cell 0x"<< std::hex << hwid.get_compact() << std::dec << " Ramp:";
422 for (size_t i=0;i<s;i++) {
423 patch.m_vRamp[i]+=ramp.m_vRamp[i];
424 msg() << MSG::DEBUG << ramp.m_vRamp[i] << " ";
425 }
426 msg() << MSG::DEBUG << endmsg;
427 nCells++;
428 }
429 if (nCells==0) {
430 if(isphi) {
431 ATH_MSG_ERROR ( "No good ramp with same phi found!" );
432 } else {
433 ATH_MSG_ERROR ( "No good ramp with same FEB found!" );
434 }
435 return false;
436 }
437 for (size_t i=0;i<s;i++)
438 patch.m_vRamp[i]=patch.m_vRamp[i]/nCells;
439
440 //FIXME: We should somehow watch the rms....
441 msg() << MSG::INFO << "Patched Ramp (based on " << nCells << " channels):" ;
442 for (size_t i=0;i<s;i++)
443 msg() << MSG::INFO << " " << patch.m_vRamp[i];
444 msg() << MSG::INFO << endmsg;
445 return true;
446}
447
448
449template<class CONDITIONSCONTAINER>
450bool LArCalibPatchingAlg<CONDITIONSCONTAINER>::getAverage(const HWIdentifier chid, const int gain, LArOFCP1& patch, const LArBadChannelCont* bcCont, const LArOnOffIdMapping* cabling, bool /*isphi*/) {
451
452 std::vector<HWIdentifier>& symCells=getPhiRing(chid, bcCont, cabling);
453
454 if (symCells.empty()) {
455 ATH_MSG_ERROR ( "No symmetry cells found!" );
456 return false;
457 }
458
459 const size_t nPhases=m_contIn->get(symCells[0],gain).m_vOFC_a.size();
460 if (!nPhases) {
461 ATH_MSG_ERROR ( "OFC of neighbor nPhase=0!" );
462 return false;
463 }
464 const size_t nSamples=m_contIn->get(symCells[0],gain).mvOFC_a[0].size();
465 if (!nSamples) {
466 ATH_MSG_ERROR ( "OFC of neighbor nSamples=0!" );
467 return false;
468 }
469
470 float timeOffset = m_contIn->get(symCells[0],gain).m_timeOffset;
471 float timeBinWidth = m_contIn->get(symCells[0],gain).m_timeBinWidth;
472 std::vector<std::vector<float> > ofc_a;
473 std::vector<std::vector<float> > ofc_b;
474 ofc_a.resize(nPhases,std::vector<float>(nSamples));
475 ofc_b.resize(nPhases,std::vector<float>(nSamples));
476
477 unsigned nCells=0;
478 for (HWIdentifier hwid : symCells) {
479 const LArOFCP1& ofc=m_contIn->get(hwid,gain);
480 if (ofc.OFC_aSize()==0 || ofc.OFC_bSize()==0) continue; //This one is empty...
481 if (ofc.OFC_aSize()!=nPhases) {
482 ATH_MSG_WARNING ("Cell with same phi but different nPhases found! Ignored" );
483 continue;
484 }
485 if (ofc.timeOffset()!=timeOffset) {
486 ATH_MSG_WARNING ("Cell with same phi but different time-offset found! Ignored" );
487 continue;
488 }
489 if (ofc.timeBinWidth()!=timeBinWidth) {
490 ATH_MSG_WARNING ("Cell with same phi but different time-offset found! Ignored" );
491 continue;
492 }
493
494 ATH_MSG_DEBUG ( "Adding cell 0x"<< std::hex << hwid.get_compact() << std::dec );
495 for (size_t iPhase=0;iPhase<nPhases;++iPhase) {
496 //Check size of vector?
497 for (size_t iSample=0;iSample<nSamples;++iSample) {
498 ofc_a[iPhase][iSample]+=ofc.OFC_a(iPhase)[iSample];
499 ofc_b[iPhase][iSample]+=ofc.OFC_b(iPhase)[iSample];
500 }
501 }
502 nCells++;
503 }
504 if (nCells==0) {
505 ATH_MSG_ERROR ( "No good OFC set with same phi found!" );
506 return false;
507 }
508
509 for (size_t iPhase=0;iPhase<nPhases;++iPhase) {
510 //Check size of vector?
511 for (size_t iSample=0;iSample<nSamples;++iSample) {
512 ofc_a[iPhase][iSample]/=nCells;
513 ofc_b[iPhase][iSample]/=nCells;
514 }
515 }
516 //FIXME: We should somehow watch the rms....
517
518 LArOFCP1 tmp (timeOffset,
519 timeBinWidth,
520 ofc_a, ofc_b);
521 patch.setFrom (tmp);
522
523 return true;
524}
525
526template<class CONDITIONSCONTAINER>
527bool LArCalibPatchingAlg<CONDITIONSCONTAINER>::getAverage(const HWIdentifier chid, const int gain, LArCaliWaveVec& patch,const LArBadChannelCont* bcCont, const LArOnOffIdMapping* cabling, bool /*isphi*/) {
528
529 const std::vector<HWIdentifier>& symCells=getPhiRing(chid, bcCont, cabling);
530
531
532 if (symCells.empty()) {
533 ATH_MSG_ERROR ( "No symmetry cells found!" );
534 return false;
535 }
536 patch.clear();
537
538 struct perDAC_t {
539 std::vector<std::tuple<HWIdentifier,double,const LArCaliWave*> > tmax_wave; //Identifier, tmax and ptr to wave, all neighbors
540 double tmaxAvg=0; //average peak time of all neighbors
541 };
542
543 LArWaveHelper wHelper;
544
545 // Organize waves per DAC and calculate tmax (peaking time)
546 std::map<int,perDAC_t> neighbors_per_dac; //In most cases, there is only one DAC, eg one entry in this map
547
548 ATH_MSG_DEBUG(" symCells size "<<symCells.size());
549 for (HWIdentifier hwid : symCells) {
550 for (const LArCaliWave& cwave : m_contIn->get(hwid,gain)) {
551 ATH_MSG_VERBOSE("found wave in channel " << m_onlineHelper->channel_name(hwid) << ", gain " << gain);
552 const int ourDAC = cwave.getDAC();
553 double tmax=-1;
554 wHelper.getDMax(cwave, tmax);
555 if (tmax > 0 ) {
556 auto& dacWave=neighbors_per_dac[ourDAC];
557 dacWave.tmax_wave.emplace_back(hwid,tmax,&cwave);
558 dacWave.tmaxAvg+=tmax;
559 }
560 else {
561 ATH_MSG_WARNING("Ignoring wave with peak-time=" << tmax << ", DAC=" << ourDAC << " found in channel " << m_onlineHelper->channel_name(hwid) << ", gain " << gain);
562 }
563 }//end loop over DACs
564 }// end loop over sym-cells
565
566 ATH_MSG_DEBUG(" neighbors_per_dac size "<<neighbors_per_dac.size());
567
568 for (auto& dacWave : neighbors_per_dac) {
569 dacWave.second.tmaxAvg/=dacWave.second.tmax_wave.size();
570 ATH_MSG_DEBUG("Average tmax computed " << dacWave.second.tmaxAvg << " for DAC=" << dacWave.first << ", to patch channel " << m_onlineHelper->channel_name(chid) << ", gain " << gain);
571 }
572
573 //Align waves accoring to their peak-time and sum them
574 std::vector<std::pair<LArCaliWave,unsigned> > alignedWaveSums;
575
576 for (const auto& dacWave : neighbors_per_dac) {//loop over DAC values
577 const int& dac=dacWave.first;
578 const perDAC_t& neighbors=dacWave.second;
579 const double& tmaxAvg=neighbors.tmaxAvg;
580 bool first=true;
581
582 for (const auto& [hwid, tmax, wave] : neighbors.tmax_wave) {
583 if (std::fabs(tmaxAvg-tmax) > wave->getWave().size()*wave->getDt()/2.0) {//Don't allow very long time shifts
584 ATH_MSG_WARNING("Peaking time of symmetric channel " << m_onlineHelper->channel_name(hwid)
585 << ", DAC=" << dac << ", gain=" << gain << " is too far off the average (" << std::fabs(tmaxAvg-tmax) << "). Ignoring.");
586 continue;
587 }
588 if (first) {
589 //First (useable) wave for this DAC value. Initialize a LArCaliWave object for it
590 alignedWaveSums.emplace_back(LArCaliWave(wHelper.Dtranslate(*wave, tmaxAvg - tmax).getWave(),wave->getDt(),wave->getDAC(),wave->getIsPulsedInt(),wave->getFlag()),1);
591 ATH_MSG_DEBUG("Adding wave of symmetric channel " << m_onlineHelper->channel_name(hwid)
592 << ", DAC=" << dac << ", gain=" << gain << " shifted by " << tmaxAvg-tmax);
593 first=false;
594 }
595 else {
596 //Subsequent waves fro this DAC value: Add them.
597 alignedWaveSums.back().first+=wHelper.Dtranslate(*wave, tmaxAvg - tmax);
598 alignedWaveSums.back().second++;
599 ATH_MSG_DEBUG("Summing wave of symmetric channel " << m_onlineHelper->channel_name(hwid)
600 << ", DAC=" << dac << ", gain=" << gain << " shifted by " << tmaxAvg-tmax);
601 }
602 }//end loop over symmetic waves for one dac value
603 if (first) {
604 ATH_MSG_ERROR("Cannot calculate patch wave for channel " << m_onlineHelper->channel_name(chid) << ", gain="<< gain << ", DAC=" << dac << ", no usable neighbors found");
605 return false;
606 }
607
608 }//end loop over DAC values
609
610 //Final loop to divide wave by number-of-waves to get the average, then push-back into return container
611 for (auto& waveSum : alignedWaveSums) { //Loop over DAC values
612 LArCaliWave& wave=waveSum.first;
613 wave*=(1./waveSum.second);
614 ATH_MSG_INFO("Calculated average wave for channel " << m_onlineHelper->channel_name(chid) << ", gain="<< gain << ", DAC=" << waveSum.first.getDAC()
615 << ", based on " << waveSum.second << " neighbors");
616 patch.push_back(wave);
617 }
618 return true;
619}
620
621template<class CONDITIONSCONTAINER>
622bool LArCalibPatchingAlg<CONDITIONSCONTAINER>::getAverage(const HWIdentifier chid, const int gain, LArAutoCorrP1& patch, const LArBadChannelCont* bcCont, const LArOnOffIdMapping* /*cabling*/, bool isphi) {
623
624 ATH_MSG_DEBUG ( "Starting getAverage for LArAutoCorr" );
625 if(isphi) {
626 ATH_MSG_ERROR ( "No phi-average for AutoCorr!" );
627 return false;
628 }
629 std::vector<HWIdentifier>& symCells = getFEBChans(chid, bcCont);
630 if (symCells.empty()) {
631 ATH_MSG_ERROR ( "No symmetry cells found!" );
632 return false;
633 }
634 size_t s=m_contIn->get(symCells[0],gain).m_vAutoCorr.size();
635 patch.m_vAutoCorr.clear();
636 patch.m_vAutoCorr.resize(s);
637 unsigned nCells=0;
638 for (HWIdentifier hwid : symCells) {
639 const LArAutoCorrP1& ac=m_contIn->get(hwid,gain);
640 if (ac.m_vAutoCorr.size()==0) continue; //This one is empty...
641 if (ac.m_vAutoCorr.size()!=s) {
642 ATH_MSG_WARNING ("Cell with same FEB but different size of autocorr found!" );
643 continue;
644 }
645 msg() << MSG::DEBUG << "Adding cell 0x"<< std::hex << hwid.get_compact() << std::dec << " AC:";
646 for (size_t i=0;i<s;i++) {
647 patch.m_vAutoCorr[i]+=ac.m_vAutoCorr[i];
648 msg() << MSG::DEBUG << ac.m_vAutoCorr[i] << " ";
649 }
650 msg() << MSG::DEBUG << endmsg;
651 nCells++;
652 }
653 if (nCells==0) {
654 ATH_MSG_ERROR ( "No good autocorr with same FEB found!" );
655 return false;
656 }
657 for (size_t i=0;i<s;i++)
658 patch.m_vAutoCorr[i]=patch.m_vAutoCorr[i]/nCells;
659
660 //FIXME: We should somehow watch the rms....
661 msg() << MSG::INFO << "Patched autocorr (based on " << nCells << " channels):" ;
662 for (size_t i=0;i<s;i++)
663 msg() << MSG::INFO << " " << patch.m_vAutoCorr[i];
664 msg() << MSG::INFO << endmsg;
665 return true;
666}
667
668#ifdef LARRAWCONDITIONS_LARMPHYSOVERMCALP
669template<class CONDITIONSCONTAINER>
670bool LArCalibPatchingAlg<CONDITIONSCONTAINER>::getAverage(const HWIdentifier chid, const int gain, LArMphysOverMcalP1& patch, const LArBadChannelCont* bcCont, const LArOnOffIdMapping* cabling, bool isphi) {
671
672 std::vector<HWIdentifier>& symCells=getPhiRing(chid, bcCont, cabling);
673
674 patch.m_MphysOverMcal=0;
675
676 unsigned nCells=0;
677 for (HWIdentifier hwid : symCells) {
678 const float mPmC=m_contIn->get(hwid,gain);
679 if (mPmC>0) {
680 patch.m_MphysOverMcal+=mPmC;
681 nCells++;
682 }
683 }
684
685 if (nCells==0) {
686 ATH_MSG_ERROR ( "No good symmetry cells found!" );
687 return false;
688 }
689 patch.m_MphysOverMcal/=nCells;
690 return true;
691}
692#endif
693
694
695
696#ifdef LARRAWCONDITIONS_LARSINGLEFLOATP
697template<class CONDITIONSCONTAINER>
698bool LArCalibPatchingAlg<CONDITIONSCONTAINER>::getAverage(const HWIdentifier chid, const int gain, LArSingleFloatP& patch, const LArBadChannelCont* bcCont, const LArOnOffIdMapping* cabling, bool /*isphi*/) {
699
700 std::vector<HWIdentifier>& symCells=getPhiRing(chid, bcCont, cabling);
701
702 patch.m_data=0;
703
704 unsigned nCells=0;
705 for (HWIdentifier hwid : symCells) {
706 const LArSingleFloatP& sf=m_contIn->get(hwid,gain);
707 if (!sf.isEmpty()) {
708 patch.m_data+=sf.m_data;
709 nCells++;
710 }
711 }
712
713 if (nCells==0) {
714 ATH_MSG_ERROR ( "No good symmetry cells found!" );
715 return false;
716 }
717 patch.m_data/=nCells;
718 return true;
719}
720#endif
721
722template<class CONDITIONSCONTAINER>
723bool LArCalibPatchingAlg<CONDITIONSCONTAINER>::setZero(const HWIdentifier chid, const int gain, LArRampP1& patch) {
724
725 size_t s=m_contIn->get(chid,gain).m_vRamp.size();
726 patch.m_vRamp.clear();
727 patch.m_vRamp.resize(s);
728 for (size_t i=0; i<s; ++i) patch.m_vRamp[i] = 0.;
729 return true;
730}
731
732template<class CONDITIONSCONTAINER>
733bool LArCalibPatchingAlg<CONDITIONSCONTAINER>::setZero(const HWIdentifier chid, const int gain, LArOFCP1& patch) {
734
735 const size_t nPhases=m_contIn->get(chid,gain).m_vOFC_a.size();
736 if (!nPhases) {
737 ATH_MSG_ERROR ( "OFC of nPhase=0 !" );
738 return false;
739 }
740 const size_t nSamples=m_contIn->get(chid,gain).mvOFC_a[0].size();
741 if (!nSamples) {
742 ATH_MSG_ERROR ( "OFC of nSamples=0 !" );
743 return false;
744 }
745
746 LArOFCP1 newvals (patch.timeOffset(), patch.timeBinWidth(),
747 std::vector<std::vector<float> > (nPhases, std::vector<float> (nSamples, 0)),
748 std::vector<std::vector<float> > (nPhases, std::vector<float> (nSamples, 0)));
749 patch.setFrom (newvals);
750 return true;
751}
752
753template<class CONDITIONSCONTAINER>
754bool LArCalibPatchingAlg<CONDITIONSCONTAINER>::setZero(const HWIdentifier /*chid*/, const int /*gain*/, LArCaliWaveVec& /*patch*/) {
755 ATH_MSG_ERROR ( "Not implemented, should not come here !!!");
756 return false;
757}
758
759template<class CONDITIONSCONTAINER>
760bool LArCalibPatchingAlg<CONDITIONSCONTAINER>::setZero(const HWIdentifier chid, const int gain, LArAutoCorrP1& patch) {
761
762 size_t s=m_contIn->get(chid,gain).m_vAutoCorr.size();
763 patch.m_vAutoCorr.clear();
764 patch.m_vAutoCorr.resize(s);
765 for (size_t i=0; i<s; ++i) patch.m_vAutoCorr[i] = 0.;
766 return true;
767}
768
769#ifdef LARRAWCONDITIONS_LARSINGLEFLOATP
770template<class CONDITIONSCONTAINER>
771bool LArCalibPatchingAlg<CONDITIONSCONTAINER>::setZero(LArSingleFloatP& patch) {
772 patch.m_data=0.;
773 return true;
774}
775#endif
776
777