ATLAS Offline Software
Loading...
Searching...
No Matches
LArOFCAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5// LArOFC: Algorithm to calculate optimal filtering constants.
6
8
20
21#include "CoralBase/Blob.h"
23
27#include "CaloDetDescr/CaloDetDescrElement.h"
31
32#include <cassert>
33#include <tuple> //std::ignore
34
35#include "tbb/parallel_for.h"
36
37//#define LAROFCALG_DEBUGOUTPUT
38
39
40LArOFCAlg::LArOFCAlg(const std::string& name, ISvcLocator* pSvcLocator)
41 : AthAlgorithm(name, pSvcLocator)
42{}
43
44
45
47
49
50 if ( m_nSamples>32 ) {
51 ATH_MSG_ERROR( "You are not allowed to compute OFC for Nsamples = " << m_nSamples ) ;
52 return StatusCode::FAILURE;
53 }
54
55 StatusCode sc = m_AutoCorrDecoder.retrieve();
56 if (sc.isFailure()) {
57 ATH_MSG_FATAL( "Could not retrieve AutoCorrDecoder " << m_AutoCorrDecoder );
58 return StatusCode::FAILURE;
59 } else {
60 ATH_MSG_INFO( "Retrieved Decoder Tool: "<< m_AutoCorrDecoder );
61 }
62
63
64 if (m_computeV2) {
65 sc = m_AutoCorrDecoderV2.retrieve();
66 if (sc.isFailure()) {
67 ATH_MSG_FATAL( "Could not retrieve AutoCorrDecoderV2 " << m_AutoCorrDecoderV2 );
68 return StatusCode::FAILURE;
69 } else {
70 ATH_MSG_INFO( "Retrieved Decoder Tool: "<< m_AutoCorrDecoderV2 );
71 }
72 }
73
74 if ( m_isSC ) {
75 const LArOnline_SuperCellID* ll;
76 sc = detStore()->retrieve(ll, "LArOnline_SuperCellID");
77 if (sc.isFailure()) {
78 msg(MSG::ERROR) << "Could not get LArOnlineID helper !" << endmsg;
79 return StatusCode::FAILURE;
80 }
81 else {
82 m_onlineID = static_cast<const LArOnlineID_Base*>(ll);
83 ATH_MSG_DEBUG("Found the LArOnlineID helper");
84 }
85 } else { // m_isSC
86 const LArOnlineID* ll;
87 sc = detStore()->retrieve(ll, "LArOnlineID");
88 if (sc.isFailure()) {
89 msg(MSG::ERROR) << "Could not get LArOnlineID helper !" << endmsg;
90 return StatusCode::FAILURE;
91 }
92 else {
93 m_onlineID = static_cast<const LArOnlineID_Base*>(ll);
94 ATH_MSG_DEBUG(" Found the LArOnlineID helper. ");
95 }
96 }
97
98 ATH_CHECK( m_cablingKeySC.initialize(m_isSC) );
100 ATH_CHECK( m_cablingKey.initialize(!m_isSC) );
101 ATH_CHECK( m_caloMgrKey.initialize(!m_isSC) );
102
103 ATH_MSG_INFO( "Number of wave points needed : " << m_nPoints ) ;
104 if (m_computeV2) {
105 ATH_MSG_INFO( "Will compute two flavors of OFCs" );
106 ATH_MSG_INFO( "Version 1: useDelta= " << m_useDelta <<", output key: " << m_ofcKey << " AutoCorrDecoder: " << m_AutoCorrDecoder.name() );
107 ATH_MSG_INFO( "Version 2: useDelta= " << m_useDeltaV2 <<", output key: " << m_ofcKeyV2 << " AutoCorrDecoder: " << m_AutoCorrDecoderV2.name() );
108 }
109 return StatusCode::SUCCESS;
110}
111
112
113StatusCode LArOFCAlg::stop()
114{
115
116 ATH_MSG_DEBUG( "In LArOFCAlg finalize()");
117
118 ATH_MSG_INFO( "Number of samples : " << m_nSamples ) ;
119 ATH_MSG_INFO( "Number of delays acquired : " << m_nDelays ) ;
120 ATH_MSG_INFO( "Number of phases in OFC : " << m_nPhases ) ;
121 ATH_MSG_INFO( "Spacing between two phases : " << m_dPhases ) ;
122
123
124 const LArOnOffIdMapping* cabling{nullptr};
125 if(m_isSC) {
127 ATH_CHECK(cablingHdl.isValid());
128 cabling = *cablingHdl;
129
130 if (m_useDelta == 3 || m_useDeltaV2==3){
132 ATH_CHECK(caloSuperCellMgrHandle.isValid());
133 m_calo_dd_man = *caloSuperCellMgrHandle;
134 }
135 }
136 else {
138 ATH_CHECK(cablingHdl.isValid());
139 cabling = *cablingHdl;
140
141 if (m_useDelta == 3 || m_useDeltaV2==3){
143 ATH_CHECK(caloMgrHandle.isValid());
144 m_calo_dd_man = *caloMgrHandle;
145 }
146 }
147
148 if ( m_timeShift ) {
149 if( m_timeShiftByIndex == -1 ) {
150 ATH_MSG_INFO( " Will use helper class for start time." );
151 } else {
152 ATH_MSG_INFO( " Manually shifting pulses by time index " << m_timeShiftByIndex );
153 }
154 }
155
156 if (!m_larPhysWaveBinKey.empty()) {
158 }
159
160 if (m_readCaliWave) {
162 }
163 else {
164 ATH_CHECK(this->initPhysWaveContainer(cabling));
165 }
166
167 if (m_readDSPConfig) {
168 const AthenaAttributeList* attrList=nullptr;
169 ATH_CHECK(detStore()->retrieve(attrList, m_DSPConfigFolder));
170
171 const coral::Blob& blob = (attrList->coralList())["febdata"].data<coral::Blob>();
172 if (blob.size()<3) {
173 ATH_MSG_INFO( "Found empty blob, nothing to do");
174 } else {
175 m_DSPConfig = std::make_unique<LArDSPConfig>(attrList);
176 }
177 }
178
179 if (m_allChannelData.empty()) {
180 ATH_MSG_ERROR( "No input waves found" );
181 return StatusCode::FAILURE;
182 }
183
185 if (m_nThreads>-1) {
186 //There are sone external tools, etc. that potentially cached stuff.
187 //We need to call them at least once to make sure all caches are filled before we go multi-threaded
189
190 m_AutoCorrDecoder->AutoCorr(chanData.chid,(CaloGain::CaloGain)chanData.gain,m_nSamples);
191 if (m_computeV2)
192 m_AutoCorrDecoderV2->AutoCorr(chanData.chid,(CaloGain::CaloGain)chanData.gain,m_nSamples);
193
194 Identifier id=cabling->cnvToIdentifier(chanData.chid);
195 if (m_useDelta==3 || m_useDeltaV2) {
196 m_calo_dd_man->get_element(id);
197 }
198
199 std::ignore = m_onlineID->isFCALchannel(chanData.chid);
200
201
202 if (!m_larPhysWaveBinKey.empty()) {
203 m_larPhysWaveBin->bin(chanData.chid,(CaloGain::CaloGain)chanData.gain);
204 }
206 std::unique_ptr<tbb::global_control> tbbgc;
207
208 if (m_nThreads>0) {
209 tbbgc=std::make_unique<tbb::global_control>( tbb::global_control::max_allowed_parallelism, m_nThreads);
210 }
211
212 //Instanciated the functor and start parallel_for
213 Looper looper(&m_allChannelData,cabling, this);
214 tbb::blocked_range<size_t> range(0, m_allChannelData.size());
215 ATH_MSG_INFO( "Starting parallel execution" );
216 tbb::parallel_for(tbb::blocked_range<size_t>(0, m_allChannelData.size()),looper);
217
218 ATH_MSG_INFO( "Done with parallel execution" );
219
220 }
221 else {
222 ATH_MSG_INFO( "Single threaded execution" );
223 for (perChannelData_t& chanData : m_allChannelData) {
224 this->process(chanData,cabling);
225 }
226 }
227
229
230 // OFC persistent object
231 std::unique_ptr<LArOFCComplete> larOFCComplete=std::make_unique<LArOFCComplete>();
232 StatusCode sc = larOFCComplete->setGroupingType(m_groupingType,msg());
233 if (sc.isFailure()) {
234 ATH_MSG_ERROR( "Failed to set groupingType for LArOFCComplete object" );
235 return sc;
236 }
237 sc=larOFCComplete->initialize();
238 if (sc.isFailure()) {
239 ATH_MSG_ERROR( "Failed initialize LArOFCComplete object" );
240 return sc;
241 }
242
243
244 std::unique_ptr<LArOFCComplete> larOFCCompleteV2=std::make_unique<LArOFCComplete>();
245 sc = larOFCComplete->setGroupingType(m_groupingType,msg());
246 if (sc.isFailure()) {
247 ATH_MSG_ERROR( "Failed to set groupingType for LArOFCComplete object" );
248 return sc;
249 }
250 sc=larOFCCompleteV2->initialize();
251 if (sc.isFailure()) {
252 ATH_MSG_ERROR( "Failed initialize LArOFCComplete object" );
253 return sc;
254 }
255
256
257 std::unique_ptr<LArOFCBinComplete> larOFCBinComplete;
258 if (m_storeMaxPhase) {
259 larOFCBinComplete=std::make_unique<LArOFCBinComplete>();
260 sc=larOFCBinComplete->setGroupingType(m_groupingType,msg());
261 if (sc.isFailure()) {
262 ATH_MSG_ERROR( "Failed to set groupingType for LArOFCBinComplete object" );
263 return sc;
264 }
265 sc = larOFCBinComplete->initialize();
266 if ( sc.isFailure() ) {
267 ATH_MSG_ERROR( "Could not initialize LArOFCComplete data object - exit!" ) ;
268 return sc ;
269 }
270 }
271
272 // LArShape persistent object
273 std::unique_ptr<LArShapeComplete> larShapeComplete;
274 if (m_fillShape) {
275 larShapeComplete = std::make_unique<LArShapeComplete>();
276 sc=larShapeComplete->setGroupingType(m_groupingType,msg());
277 if (sc.isFailure()) {
278 ATH_MSG_ERROR( "Failed to set groupingType for LArShapeComplete object" );
279 return sc;
280 }
281 sc=larShapeComplete->initialize();
282 if (sc.isFailure()) {
283 ATH_MSG_ERROR( "Failed initialize LArShapeComplete object" );
284 return sc;
285 }
286 }
287
288
289 //Counters (for information only):
290 unsigned nChannels=0;
291 unsigned nFailed=0;
292
293 for (const perChannelData_t& chanData : m_allChannelData) {
294 ++nChannels;
295 if (chanData.faultyOFC) ++nFailed;
296 // register channel to LArOFCComplete
297 const HWIdentifier ch_id=chanData.chid;
298 const int gain=chanData.gain;
299 ATH_MSG_DEBUG( "add to LArOFCComplete, channel " << m_onlineID->channel_name(ch_id) << ", gain=" << (int)gain);
300 const std::vector<std::vector<float> > & allPhaseOFCa=chanData.ofc_a;
301 const std::vector<std::vector<float> > & allPhaseOFCb=chanData.ofc_b;
302 const std::vector<std::vector<float> > & allPhaseShape=chanData.shape;
303 const std::vector<std::vector<float> > & allPhaseShapeDer=chanData.shapeDer;
304 larOFCComplete->set(ch_id,gain,allPhaseOFCa,allPhaseOFCb,chanData.tstart,chanData.timeBinWidthOFC);
305 if (larOFCBinComplete) larOFCBinComplete->set(ch_id,gain,chanData.phasewMaxAt3);
306 if ( m_fillShape ) larShapeComplete->set(ch_id,gain,allPhaseShape,allPhaseShapeDer,chanData.tstart,chanData.timeBinWidthOFC);
307
308
309 if (m_computeV2) {
310 const std::vector<std::vector<float> > & allPhaseOFCV2a=chanData.ofcV2_a;
311 const std::vector<std::vector<float> > & allPhaseOFCV2b=chanData.ofcV2_b;
312 larOFCCompleteV2->set(ch_id,gain,allPhaseOFCV2a,allPhaseOFCV2b,chanData.tstart,chanData.timeBinWidthOFC);
313 }
314
315 } // end loop over m_allChannelData
316
317 ATH_MSG_INFO( " Summary : Computed OFCs for " << nChannels << " channels * gains" );
318 if (nFailed)
319 ATH_MSG_ERROR( "Number of channels * gains with failed OFC verification: " << nFailed );
320
321 if ( !m_dumpOFCfile.empty()) {
322 ATH_MSG_INFO( "Dumping OFCs to file " << m_dumpOFCfile ) ;
323 larOFCComplete->dumpOFC(m_dumpOFCfile) ;
324 }
325
326 sc = detStore()->record(std::move(larOFCComplete),m_ofcKey);
327 if (sc.isFailure()) {
328 ATH_MSG_ERROR( "Could not record LArOFCComplete to DetStore with key " << m_ofcKey );
329 return StatusCode::FAILURE;
330 }
331 ATH_MSG_INFO( "LArOFCComplete object recorded with key " << m_ofcKey ) ;
332
333 // record second version of LArOFCComplete object
334 if (m_computeV2) {
335 sc = detStore()->record(std::move(larOFCCompleteV2),m_ofcKeyV2);
336 if (sc.isFailure()) {
337 ATH_MSG_ERROR( "Could not record LArOFCComplete to DetStore with key " << m_ofcKeyV2 );
338 return StatusCode::FAILURE;
339 }
340 ATH_MSG_INFO( "LArOFCComplete object recorded with key " << m_ofcKeyV2 ) ;
341 }
342
343 if (larOFCBinComplete) {
344 sc = detStore()->record(std::move(larOFCBinComplete),m_ofcBinKey);
345 if (sc.isFailure()) {
346 ATH_MSG_ERROR( "Could not record LArOFCBinCompete object" );
347 return StatusCode::FAILURE;
348 }
349 }
350
351 // record LArShapeComplete object
352 if ( m_fillShape ) {
353 ATH_MSG_DEBUG( "Trying to record LArShapeComplete object to detector store, key = " << m_shapeKey);
354 sc = detStore()->record(std::move(larShapeComplete),m_shapeKey);
355 if (sc.isFailure()) {
356 ATH_MSG_ERROR( "Could not record LArShapeComplete to DetStore with key " << m_shapeKey );
357 return StatusCode::FAILURE;
358 }
359 ATH_MSG_INFO( "LArShapeComplete object recorded to DetStore successfully with key " << m_shapeKey ) ;
360 }
361
362
363 //Undo corrections, if they are applied by this algo:
364 if (m_waveCnt_nc) {
365 ATH_CHECK(m_waveCnt_nc->undoCorrections());
366 ATH_MSG_INFO("Reverted corrections of non-cost wave container");
367 }
368
369 return StatusCode::SUCCESS;
370}
371
372
373void LArOFCAlg::process(perChannelData_t& chanData, const LArOnOffIdMapping* cabling) const {
374
375 LArWaveHelper larWaveHelper;
376 const LArWaveCumul* nextWave=chanData.inputWave;
377 if (!nextWave) {
378 ATH_MSG_ERROR( "input wave is 0" );
379 return;
380 }
381
382 if ( nextWave->getFlag() == LArWave::dac0 ) return ; // skip dac0 waves
383
384 const HWIdentifier ch_id=chanData.chid;
385 const unsigned gain=chanData.gain;
386 ATH_MSG_DEBUG( "Computing OFC for channel " << m_onlineID->channel_name(ch_id) << " in gain = " << gain);
387
388
389 // check constistency of settings
390 if ( m_nPoints > nextWave->getSize() ) {
391 ATH_MSG_ERROR( "Channel " << m_onlineID->channel_name(ch_id) <<": Wave size (" << nextWave->getSize()
392 << ") is too small to fit your OFC request (" << m_nPoints << " points)" ) ;
393 chanData.shortWave=true;
394 return;
395 }
396
397 // the current waveform
398 LArWave aWave = *nextWave; // Actually *copying* the Wave to get rid of the const: need to manipulate Wave to normalize...
399
400 if (m_larPhysWaveBin) {
401 const int bin = m_larPhysWaveBin->bin(ch_id,gain);
402 if (bin>-998) { //>ERRORCODE
403 ATH_MSG_VERBOSE("Channel " << m_onlineID->channel_name(ch_id) << ": shift by index " << bin);
404 aWave=larWaveHelper.translate(aWave,-bin,0);
405 }
406 else
407 ATH_MSG_VERBOSE("Channel 0x" << MSG::hex << ch_id.get_identifier32().get_compact() << MSG::dec << ": No valid index for shifting");
408 }//end if larPhysWaveBin
409
410
411 // normalize input wave, if requested
412 if (m_normalize) {
413 const double peak = aWave.getSample( larWaveHelper.getMax(aWave) );
414 if ( peak == 0 ) {
415 ATH_MSG_ERROR( "Wave maximum is zero, skipping channel " << m_onlineID->channel_name(ch_id) ) ;
416 return;
417 }
418
419 ATH_MSG_VERBOSE("Channel 0x" << m_onlineID->channel_name(ch_id) << " has amplitude = " << peak << ": normalizing...");
420 aWave = aWave * (1./peak);
421 }
422
423 ATH_MSG_VERBOSE("Channel " << m_onlineID->channel_name(ch_id) << " has now amplitude = " << aWave.getSample( larWaveHelper.getMax(aWave)));
424 // compute tstart to shift input wave, if requested
425 if ( m_timeShift ) {
426 if( m_timeShiftByIndex == -1 ) {
427 chanData.tstart = larWaveHelper.getStart(aWave) ;
428 } else {
429 chanData.tstart = m_timeShiftByIndex;
430 }
431 }
432
433 ATH_MSG_DEBUG("Channel" << m_onlineID->channel_name(ch_id) << ", Tstart = " << chanData.tstart);
434
435 //Calculate derivative for this wave
436 LArWave aDerivedWave = larWaveHelper.derive_smooth(aWave);
437
438 chanData.timeBinWidthOFC = m_dPhases*aWave.getDt();
439
440 float maxSampleValAt3=-1;
441
442 //prepare output vectors
443 chanData.ofc_a.resize(m_nPhases);
444 chanData.ofc_b.resize(m_nPhases);
445 chanData.shape.resize(m_nPhases);
446 chanData.shapeDer.resize(m_nPhases);
447
448 if (m_computeV2) {
449 chanData.ofcV2_a.resize(m_nPhases);
450 chanData.ofcV2_b.resize(m_nPhases);
451 }
452
453
454 const Eigen::MatrixXd acInverse=m_AutoCorrDecoder->AutoCorr(chanData.chid,(CaloGain::CaloGain)chanData.gain,m_nSamples).inverse();
455 Eigen::MatrixXd acInverseV2;
456 if (m_computeV2)
457 acInverseV2=m_AutoCorrDecoderV2->AutoCorr(chanData.chid,(CaloGain::CaloGain)chanData.gain,m_nSamples).inverse();
458
459 unsigned tShift=0;
461 if(m_DSPConfig->peakSample(m_onlineID->feb_Id(ch_id)) < 2 ) { // 2 is canonical value for peak
462 tShift = 2 - m_DSPConfig->peakSample(m_onlineID->feb_Id(ch_id));
463 }
464 }
465 if(m_forceShift) tShift=1;
466
467 ATH_MSG_DEBUG("Channel " << m_onlineID->channel_name(ch_id) << "shift: " << tShift);
468
469 for (unsigned iPhase=0;iPhase<m_nPhases;iPhase++) { //Loop over all phases
470
471 ATH_MSG_VERBOSE ("Channel " << m_onlineID->channel_name(ch_id)
472 << ", Gain = " << gain << ", Phase = " << iPhase << ":");
473
474
475 //Reference to the samples and deriviative to be filled
476 std::vector<float>& theSamples=chanData.shape[iPhase];
477 std::vector<float>& theSamplesDer=chanData.shapeDer[iPhase];
478
479 //Extract the points where we compute the OFCs from the wave and the derived wave
480 //and fill the samples an derivative vector
481 theSamples.reserve(m_nSamples);
482 theSamplesDer.reserve(m_nSamples);
483 for (unsigned iSample=0;iSample<m_nSamples;++iSample){ //Loop over all samples
484 const unsigned tbin = chanData.tstart + iPhase*m_dPhases + (iSample+tShift)*m_nDelays ;
485 theSamples.push_back( aWave.getSample(tbin) );
486 theSamplesDer.push_back( aDerivedWave.getSample(tbin) );
487 } //End loop over samples
488
489
490 if (m_storeMaxPhase && m_nSamples>2 && theSamples[2]>maxSampleValAt3) {
491 maxSampleValAt3=theSamples[2];
492 chanData.phasewMaxAt3=iPhase;
493 }
494
495 bool thisChanUseDelta=useDelta(ch_id,m_useDelta,cabling);
496 bool thisChanUseDeltaV2=m_computeV2 && useDelta(ch_id,m_useDeltaV2,cabling);
497 Eigen::VectorXd delta;
498
499 if (thisChanUseDelta || thisChanUseDeltaV2) { // will need delta for at least one of the two versions
500 std::vector<float> theSamples32;
501 theSamples32.reserve(32);
502 for (unsigned iSample=0;iSample<32 ;++iSample){ //Loop over all samples
503 const unsigned tbin = chanData.tstart + iPhase*m_dPhases + (iSample+tShift)*m_nDelays ;
504 if (tbin>=aWave.getSize()) continue;
505 theSamples32.push_back( aWave.getSample(tbin) );
506 } //End loop over samples
507 delta=getDelta(theSamples32,ch_id,m_nSamples);
508 }
509
510 //OFC V1 computiation (i.e. not pileup-optimized)
511 //Reference to the OFCa and OFCb to be filled
512 std::vector<float>& vOFC_a= chanData.ofc_a[iPhase];
513 std::vector<float>& vOFC_b= chanData.ofc_b[iPhase];
514
515 if(m_computePed){
516 optFiltPed(theSamples,theSamplesDer,acInverse,vOFC_a,vOFC_b);
517 } else {
518 if (thisChanUseDelta) {
519 optFiltDelta(theSamples,theSamplesDer,acInverse,delta,vOFC_a,vOFC_b);
520 }
521 else { //don't use Delta
522 optFilt(theSamples,theSamplesDer,acInverse,vOFC_a,vOFC_b);
523 }
524 }
525
526 // verify OFC consistency
527 if (m_verify) {
528 chanData.faultyOFC |= verify(chanData.chid,vOFC_a,vOFC_b,theSamples,"OFC",iPhase);
529 }
530
531
532 if (m_computeV2) {
533 //OFC V2 computiation (i.e. pileup-optimized)
534 //Reference to the OFCa and OFCb to be filled
535 std::vector<float>& vOFCV2_a= chanData.ofcV2_a[iPhase];
536 std::vector<float>& vOFCV2_b= chanData.ofcV2_b[iPhase];
537
538 if(m_computePed){
539 optFiltPed(theSamples,theSamplesDer,acInverseV2,vOFCV2_a,vOFCV2_b);
540 } else {
541 if (thisChanUseDeltaV2) {
542 optFiltDelta(theSamples,theSamplesDer,acInverseV2,delta,vOFCV2_a,vOFCV2_b);
543 }
544 else { //don't use Delta
545 optFilt(theSamples,theSamplesDer,acInverseV2,vOFCV2_a,vOFCV2_b);
546 }
547 }
548
549 // verify OFC consistency
550 if (m_verify) {
551 chanData.faultyOFC |= verify(chanData.chid,vOFCV2_a,vOFCV2_b,theSamples,"OFCV2",iPhase);
552 }
553 }//end if computeV2
554 } //End loop over all phases
555
556 // in case we're dealing with a LArPhysWave, add any possible previous time shift
557 if (!m_readCaliWave) {
558 const LArPhysWave* pwave=dynamic_cast<const LArPhysWave*>(nextWave);
559 if (pwave)
560 chanData.tstart += pwave->getTimeOffset()+m_addOffset;
561 }
562 }
563
564
565
566
568
570
571 for (unsigned k=0 ; k<m_keylist.size() ; k++ ) { // Loop over all containers that are to be processed (e.g. different gains)
572 ATH_MSG_INFO( "Processing WaveContainer from StoreGate! key = " << m_keylist[k] );
573
574 const LArPhysWaveContainer* waveCnt;
575 StatusCode sc=detStore()->retrieve(waveCnt,m_keylist[k]);
576 if (sc.isFailure()) {
577 ATH_MSG_ERROR( "Failed to retrieve a LArPhysWaveContainer with key " << m_keylist[k] );
578 return sc;
579 }
580
581 m_allChannelData.reserve(std::max(m_allChannelData.size()*3/2,m_allChannelData.size()+128*waveCnt->size()));// Size doesn't give the expected response on a ConditionsContainer
582
583 for (unsigned gain = CaloGain::LARHIGHGAIN ; gain < CaloGain::LARNGAIN ; gain++ ) { // loop on possible gains
584 WAVEIT it=waveCnt->begin(gain);
585 WAVEIT it_e=waveCnt->end(gain);
586 for (;it!=it_e;++it) {
587 const HWIdentifier chid=it.channelId();
588 if (cabling->isOnlineConnected (chid)){
589 const LArWaveCumul* wave= &(*it); //down-cast
590 if (!wave->isEmpty()) {
591 m_allChannelData.emplace_back(wave, chid,gain);
592 }
593 }
594 } //end loop over channels
595 }//end loop over gains
596 }//end loop over SG keys
597 return StatusCode::SUCCESS;
598}
599
600
602
604 for (unsigned k=0 ; k<m_keylist.size() ; k++ ) { // Loop over all containers that are to be processed (e.g. different gains)
605 ATH_MSG_INFO( "Processing WaveContainer from StoreGate! key = " << m_keylist[k] );
606
607 //Input cali-wave might come from the same job. In this case we see a non-const container in SG probably w/o corrections applied.
608 //Try non-const retrieve:
609 const LArCaliWaveContainer* waveCnt = nullptr;
611 if (m_waveCnt_nc) {
612 waveCnt=m_waveCnt_nc; //Retain const pointer
613 if (!m_waveCnt_nc->correctionsApplied()) {
614 ATH_MSG_INFO( "LArCaliWaveContainer: Corrections not yet applied, applying them now..." );
615 if (m_waveCnt_nc->applyCorrections().isFailure()) {
616 ATH_MSG_ERROR( "Failed to apply corrections to LArCaliWaveContainer!" );
617 return StatusCode::FAILURE;
618 }
619 else {
620 ATH_MSG_INFO("Applied corrections to non-const Wave container");
621 }
622 }
623 }
624 else {
625 waveCnt=detStore()->tryConstRetrieve<LArCaliWaveContainer>(m_keylist[k]);
626 if (!waveCnt) {
627 ATH_MSG_ERROR( "Failed to retrieve a LArCaliWaveContainer with key " << m_keylist[k] );
628 return StatusCode::FAILURE;
629 }
630 }
631
632
633 m_allChannelData.reserve(std::max(m_allChannelData.size()*3/2,m_allChannelData.size()+128*waveCnt->size()));// Size doesn't give the expected response on a ConditionsContainer
634
635 for (unsigned gain = CaloGain::LARHIGHGAIN ; gain < CaloGain::LARNGAIN ; gain++ ) { // loop on possible gains
636 WAVEIT it=waveCnt->begin(gain);
637 WAVEIT it_e=waveCnt->end(gain);
638 for (;it!=it_e;++it) {
639 const LArCaliWaveVec& wVec=*it;
640 for (const auto& cw : wVec) {
641 const LArWaveCumul* wave= &(cw); //down-cast
642 if (!wave->isEmpty()) {
643 m_allChannelData.emplace_back(wave,it.channelId(),gain);
644 }
645 }
646 } //end loop over channels
647 }//end loop over gains
648 }//end loop over SG keys
649 return StatusCode::SUCCESS;
650}
651
652
653void LArOFCAlg::optFilt(const std::vector<float> &gWave, const std::vector<float> &gDerivWave, const Eigen::MatrixXd& acInverse, //input variables
654 std::vector<float>& vecOFCa, std::vector<float>& vecOFCb) { // Output variables;
655 assert(gWave.size()==gDerivWave.size());
656 //assert autoCorr size ....
657 const int optNpt = gWave.size();
658
659 Eigen::VectorXd gResp(optNpt), gDerivResp(optNpt);
660 for (int i=0;i<optNpt;i++) {
661 gResp[i] = gWave[i];
662 gDerivResp[i] = gDerivWave[i];
663 }
664
665 Eigen::Matrix2d isol;
666 isol <<
667 (gResp.transpose()*acInverse*gResp)[0],
668 (gResp.transpose()*acInverse*gDerivResp)[0],
669 (gDerivResp.transpose()*acInverse*gResp)[0],
670 (gDerivResp.transpose()*acInverse*gDerivResp)[0];
671
672 Eigen::Vector2d Amp;
673 Eigen::Vector2d Atau;
674 Eigen::Vector2d Ktemp;
675 Eigen::Matrix2d isolInv = isol.inverse();
676
677 // we solve for the lagrange multiplers
678 Ktemp[0] = 1.;
679 Ktemp[1] = 0.;
680 Amp = isolInv*Ktemp;
681
682 Ktemp[0] = 0.;
683 Ktemp[1] = -1.;
684 Atau = isolInv*Ktemp;
685
686 // we express the a and b vectors in terms of the lagrange multipliers
687 Eigen::VectorXd OFCa = Amp[0]*acInverse*gResp + Amp[1]*acInverse*gDerivResp;
688 Eigen::VectorXd OFCb = Atau[0]*acInverse*gResp + Atau[1]*acInverse*gDerivResp;
689
690 //Convert back to std::vector
691 vecOFCa.resize(optNpt);
692 vecOFCb.resize(optNpt);
693 for (int i=0;i<optNpt;i++) {
694 vecOFCa[i]=OFCa[i];
695 vecOFCb[i]=OFCb[i];
696 }
697 }
698
699void LArOFCAlg::optFiltPed(const std::vector<float> &gWave, const std::vector<float> &gDerivWave, const Eigen::MatrixXd& acInverse, //input variables
700 std::vector<float>& vecOFCa, std::vector<float>& vecOFCb) { // Output variables;
701 assert(gWave.size()==gDerivWave.size());
702 //assert autoCorr size ....
703 const int optNpt = gWave.size();
704
705 Eigen::VectorXd gResp(optNpt), gDerivResp(optNpt);
706 for (int i=0;i<optNpt;i++) {
707 gResp[i] = gWave[i];
708 gDerivResp[i] = gDerivWave[i];
709 }
710
711 Eigen::Matrix3d isol;
712 Eigen::Vector3d Kunit(1.,1.,1.);
713 auto s3=(gDerivResp.transpose()*acInverse*gResp)[0];
714 auto s4=(gResp.transpose()*acInverse*Kunit)[0];
715 auto s5=(gDerivResp.transpose()*acInverse*Kunit)[0];
716 isol <<
717 (gResp.transpose()*acInverse*gResp)[0], s3, s4,
718 s3, (gDerivResp.transpose()*acInverse*gResp)[0], s5,
719 s4, s5, (Kunit.transpose()*acInverse*Kunit)[0];
720
721 Eigen::Vector3d Amp;
722 Eigen::Vector3d Atau;
723 Eigen::Vector3d Ktemp;
724 Eigen::Matrix3d isolInv = isol.inverse();
725
726 // we solve for the lagrange multiplers
727 Ktemp[0] = 1.;
728 Ktemp[1] = 0.;
729 Ktemp[2] = 0.;
730 Amp = isolInv*Ktemp;
731
732 Ktemp[0] = 0.;
733 Ktemp[1] = -1.;
734 Ktemp[2] = 0.;
735 Atau = isolInv*Ktemp;
736
737 // we express the a and b vectors in terms of the lagrange multipliers
738 Eigen::VectorXd OFCa = Amp[0]*acInverse*gResp + Amp[1]*acInverse*gDerivResp + Amp[2]*acInverse*Kunit;
739 Eigen::VectorXd OFCb = Atau[0]*acInverse*gResp + Atau[1]*acInverse*gDerivResp + Atau[2]*acInverse*Kunit;
740
741 //Convert back to std::vector
742 vecOFCa.resize(optNpt);
743 vecOFCb.resize(optNpt);
744 for (int i=0;i<optNpt;i++) {
745 vecOFCa[i]=OFCa[i];
746 vecOFCb[i]=OFCb[i];
747 }
748 }
749
750
751void LArOFCAlg::optFiltDelta(const std::vector<float> &gWave, const std::vector<float> &gDerivWave,
752 const Eigen::MatrixXd& acInverse, const Eigen::VectorXd& delta,
753 std::vector<float>& vecOFCa, std::vector<float>& vecOFCb) {
754
755
756
757 assert(gWave.size()==gDerivWave.size());
758 //assert autoCorr size ....
759 const int optNpt = gWave.size();
760
761 Eigen::VectorXd gResp(optNpt), gDerivResp(optNpt);
762 for (int i=0;i<optNpt;i++) {
763 gResp[i] = gWave[i];
764 gDerivResp[i] = gDerivWave[i];
765 }
766
767 // try 3X3 matrix with offsets
768
769
779 Eigen::Matrix3d isol;
780 isol <<
781 (gResp.transpose()*acInverse*gResp)[0],
782 (gResp.transpose()*acInverse*gDerivResp),
783 (gResp.transpose()*acInverse*delta)[0],
784
785 (gDerivResp.transpose()*acInverse*gResp)[0],
786 (gDerivResp.transpose()*acInverse*gDerivResp)[0],
787 (gDerivResp.transpose()*acInverse*delta)[0],
788
789 (delta.transpose()*acInverse*gResp)[0],
790 (delta.transpose()*acInverse*gDerivResp)[0],
791 (delta.transpose()*acInverse*delta)[0];
792
793
794 Eigen::Vector3d Amp;
795 Eigen::Vector3d Atau;
796 Eigen::Vector3d Ktemp;
797 Eigen::Matrix3d isolInv = isol.inverse();
798
799 // we solve for the lagrange multiplers
800
801 Ktemp[0] = 1.;
802 Ktemp[1] = 0.;
803 Ktemp[2] = 0.;
804
805 Amp = isolInv*Ktemp;
806
807 Ktemp[0] = 0.;
808 Ktemp[1] = -1.;
809 Atau = isolInv*Ktemp;
810
811 // we express the a and b vectors in terms of the lagrange multipliers
812 Eigen::VectorXd OFCa = Amp[0]*acInverse*gResp + Amp[1]*acInverse*gDerivResp + Amp[2]*acInverse * delta;
813 Eigen::VectorXd OFCb = Atau[0]*acInverse*gResp + Atau[1]*acInverse*gDerivResp + Atau[2]*acInverse * delta ;
814
815
816 //Convert back to std::vector
817 vecOFCa.resize(optNpt);
818 vecOFCb.resize(optNpt);
819 for (int i=0;i<optNpt;i++) {
820 vecOFCa[i]=OFCa[i];
821 vecOFCb[i]=OFCb[i];
822 }
823 }
824
825
826
827const float LArOFCAlg::m_fcal3Delta[5] ={0.0790199937765, 0.0952000226825, 0.0790199937765, 0.0952000226825, 0.0790199937765};
828const float LArOFCAlg::m_fcal2Delta[5]={-0.01589001104, -0.0740399733186, -0.01589001104, -0.0740399733186, -0.01589001104};
829const float LArOFCAlg::m_fcal1Delta[5] ={0.0679600232979, -0.139479996869, 0.0679600232979, -0.139479996869, 0.0679600232979};
830
831Eigen::VectorXd LArOFCAlg::getDelta(std::vector<float>& samples, const HWIdentifier chid, unsigned nSamples) const{
832
833 if (nSamples>5) nSamples=5;
834
835 Eigen::VectorXd delta(nSamples); //return value
836
837 if (m_onlineID->isFCALchannel(chid) ){
838 // FCAL use fixed delta from data.
839 const int slot = m_onlineID->slot(chid) ;
840 if ( slot <=9){ // FCAL 1
841 for (unsigned i=0;i<nSamples;++i) {
842 delta[i]=m_fcal1Delta[i];
843 }
844 }else
845 if(slot <=13){ // FCAL 2
846 for (unsigned i=0;i<nSamples;++i) {
847 delta[i]=m_fcal2Delta[i];
848 }
849 }else { //FCAL 3
850 for (unsigned i=0;i<nSamples;++i) {
851 delta[i]=m_fcal3Delta[i];
852 }
853 }
854
855 }else
856 { // from Shape
857 float odd = 0.;
858 float even = 0.;
859 for (unsigned int i = 0;i<samples.size();++i) {
860 if (i%2==0){
861 even += samples[i];
862 }
863 else {
864 odd += samples[i];
865 }
866 }
867
868 for (unsigned i=0;i<nSamples;++i) {
869 if (i%2==0)
870 delta[i]=even;
871 else
872 delta[i]=odd;
873 }
874 }
875
876 return delta;
877
878}
879
880bool LArOFCAlg::useDelta(const HWIdentifier chid, const int jobOFlag, const LArOnOffIdMapping* cabling) const {
881
882 if (jobOFlag==2){
883 return true;
884 }
885
886 if(jobOFlag==1) { // only HEC/EMECIW/FCAL
887 if (m_onlineID->isEMECIW(chid) || m_onlineID->isFCALchannel(chid) || m_onlineID->isHECchannel(chid)) {
888 return true;
889 }
890 }
891
892 if(jobOFlag==3) { // only HEC/EMECIW/FCAL1 and high eta FCAL2-3
893 if (m_onlineID->isEMECIW(chid) || m_onlineID->isHECchannel(chid)) {
894 return true;
895 }
896 else if (m_onlineID->isFCALchannel(chid) ){
897
898 if (cabling->isOnlineConnected (chid)){
899 Identifier ofl_id = cabling->cnvToIdentifier(chid);
900 const CaloDetDescrElement* dde = m_calo_dd_man->get_element(ofl_id);
901 if (! dde) {
902 ATH_MSG_ERROR( " dde = 0 , onl_id, ofl_id= "<< chid<<" "<<ofl_id );
903 return false; // Exception better?
904 }
905 if ( m_isSC ) {
907 if (sampling==CaloCell_ID::FCAL0){
908 return true;
909 }
910 else {
911 if (fabs(dde->eta())>4.0){
912 return true;
913 }
914 }
915 } else {
916 CaloCell_ID::CaloSample sampling = dde->getSampling();
917 if (sampling==CaloCell_ID::FCAL0){
918 return true;
919 }
920 else {
921 if (fabs(dde->eta())>4.0){
922 return true;
923 }
924 }
925 }
926
927 }//end if connected
928 }//end if isFCALchannel
929
930 }//else if jobOFlag=3
931
932 return false;
933}
934
935
936bool LArOFCAlg::verify(const HWIdentifier chid, const std::vector<float>& OFCa, const std::vector<float>& OFCb,
937 const std::vector<float>& Shape, const char* ofcversion, const unsigned phase) const {
938
939 bool result=false;
940 float recAmpl=0, recTime=0;
941 for (unsigned iSample=0;iSample<m_nSamples;++iSample){
942
943#ifdef LAROFCALG_DEBUGOUTPUT
944 ATH_MSG_VERBOSE("a["<<iSample<<"]="<<vOFC_a[iSample] << " b["<<iSample<<"]="<<vOFC_b[iSample]
945 << " Sample=" << aWave.getSample(tbin));
946#endif
947 recAmpl += OFCa[iSample] * Shape[iSample];
948 recTime += OFCb[iSample] * Shape[iSample];
949 } //End loop over samples
950
951 if (recAmpl != 0) {
952 recTime /= recAmpl ;
953 }
954
955 // At this point the reconstructed amplitude must be = 1 by definition, whatever the initial normalisation!
956 ATH_MSG_VERBOSE("recAmp=" << recAmpl << " ; recTime=" << recTime);
957 if ( fabs(1.-recAmpl) > m_errAmpl ) {
958 ATH_MSG_WARNING( "Applying phase " << phase << " of " << ofcversion << " to original wave yields an Amplitude of "<< recAmpl
959 << " instead of 1. -> Wrong OFCs? channel " << m_onlineID->channel_name(chid) );
961 result=true;
962 }
963 if ( fabs(recTime) > m_errTime ) {
964 ATH_MSG_WARNING( "Applying phase " << phase << " of " << ofcversion << " to original wave yields a time offset of " << recTime
965 << " -> Wrong OFCs? channel " << m_onlineID->channel_name(chid) );
967 result=true;
968 }
969 return result;
970}
971
972void LArOFCAlg::printOFCVec(const std::vector<float>& vec, MsgStream& mLog) {
973 mLog << MSG::WARNING << "OFCs";
974 for(float v : vec)
975 mLog << " " << v;
976 mLog << endmsg;
977}
978
979
980#ifdef LAROFCALG_DEBUGOUTPUT
981#undef LAROFCALG_DEBUGOUTPUT
982#endif
#define endmsg
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_VERBOSE(x,...)
#define ATH_MSG_INFO(x,...)
#define ATH_MSG_FATAL(x,...)
Helper class for offline supercell identifiers.
Definition of CaloDetDescrManager.
std::vector< size_t > vec
static Double_t sc
AthAlgorithm(const std::string &name, ISvcLocator *pSvcLocator)
Constructor.
const ServiceHandle< StoreGateSvc > & detStore() const
An AttributeList represents a logical row of attributes in a metadata table.
CaloSampling::CaloSample CaloSample
Definition CaloCell_ID.h:53
This class groups all DetDescr information related to a CaloCell.
CaloCell_ID::CaloSample getSampling() const
cell sampling
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.
Liquid Argon Cumulative Wave Container.
ConditionsMap::const_iterator ConstConditionsMapIterator
ConstConditionsMapIterator begin(unsigned int gain) const
get iterator for all channels for a gain
ConstConditionsMapIterator end(unsigned int gain) const
end of all channels for this gain
UnsignedIntegerProperty m_nSamples
Definition LArOFCAlg.h:133
SG::ReadCondHandleKey< CaloDetDescrManager > m_caloMgrKey
Definition LArOFCAlg.h:55
DoubleProperty m_errAmpl
Definition LArOFCAlg.h:146
SG::ReadCondHandleKey< LArOnOffIdMapping > m_cablingKeySC
Definition LArOFCAlg.h:53
static const float m_fcal3Delta[5]
Definition LArOFCAlg.h:827
BooleanProperty m_verify
Definition LArOFCAlg.h:125
UnsignedIntegerProperty m_nDelays
Definition LArOFCAlg.h:136
BooleanProperty m_timeShift
Definition LArOFCAlg.h:127
ToolHandle< ILArAutoCorrDecoderTool > m_AutoCorrDecoder
Definition LArOFCAlg.h:139
static const float m_fcal2Delta[5]
Definition LArOFCAlg.h:828
SG::ReadCondHandleKey< LArOnOffIdMapping > m_cablingKey
Definition LArOFCAlg.h:52
StringProperty m_ofcKeyV2
Definition LArOFCAlg.h:152
ToolHandle< ILArAutoCorrDecoderTool > m_AutoCorrDecoderV2
Definition LArOFCAlg.h:140
StatusCode initCaliWaveContainer()
IntegerProperty m_timeShiftByIndex
Definition LArOFCAlg.h:128
UnsignedIntegerProperty m_nPhases
Definition LArOFCAlg.h:134
std::unique_ptr< LArDSPConfig > m_DSPConfig
Definition LArOFCAlg.h:168
DoubleProperty m_errTime
Definition LArOFCAlg.h:147
const CaloDetDescrManager_Base * m_calo_dd_man
Definition LArOFCAlg.h:142
StringProperty m_ofcBinKey
Definition LArOFCAlg.h:155
BooleanProperty m_fillShape
Definition LArOFCAlg.h:150
IntegerProperty m_useDelta
Definition LArOFCAlg.h:160
static const float m_fcal1Delta[5]
Definition LArOFCAlg.h:829
bool useDelta(const HWIdentifier chid, const int jobOFlag, const LArOnOffIdMapping *cabling) const
BooleanProperty m_computeV2
Definition LArOFCAlg.h:162
const LArOnlineID_Base * m_onlineID
Definition LArOFCAlg.h:143
BooleanProperty m_readCaliWave
Definition LArOFCAlg.h:149
UnsignedIntegerProperty m_dPhases
Definition LArOFCAlg.h:135
IntegerProperty m_useDeltaV2
Definition LArOFCAlg.h:161
StatusCode initialize()
Definition LArOFCAlg.cxx:46
std::vector< perChannelData_t > m_allChannelData
Definition LArOFCAlg.h:94
StatusCode initPhysWaveContainer(const LArOnOffIdMapping *cabling)
const LArOFCBinComplete * m_larPhysWaveBin
Definition LArOFCAlg.h:144
static void optFilt(const std::vector< float > &gWave_in, const std::vector< float > &gDerivWave_in, const Eigen::MatrixXd &autoCorrInv, std::vector< float > &OFCa, std::vector< float > &OFCb)
static void optFiltPed(const std::vector< float > &gWave_in, const std::vector< float > &gDerivWave_in, const Eigen::MatrixXd &autoCorrInv, std::vector< float > &OFCa, std::vector< float > &OFCb)
BooleanProperty m_readDSPConfig
Definition LArOFCAlg.h:166
Eigen::VectorXd getDelta(std::vector< float > &samples, const HWIdentifier chid, unsigned nSamples) const
StringProperty m_DSPConfigFolder
Definition LArOFCAlg.h:167
BooleanProperty m_forceShift
Definition LArOFCAlg.h:170
StringProperty m_larPhysWaveBinKey
Definition LArOFCAlg.h:158
FloatProperty m_addOffset
Definition LArOFCAlg.h:137
BooleanProperty m_storeMaxPhase
Definition LArOFCAlg.h:154
StringProperty m_shapeKey
Definition LArOFCAlg.h:153
bool verify(const HWIdentifier chid, const std::vector< float > &OFCa, const std::vector< float > &OFCb, const std::vector< float > &Shape, const char *ofcversion, const unsigned phase) const
SG::ReadCondHandleKey< CaloSuperCellDetDescrManager > m_caloSuperCellMgrKey
Definition LArOFCAlg.h:60
static void printOFCVec(const std::vector< float > &vec, MsgStream &mLog)
StringProperty m_ofcKey
Definition LArOFCAlg.h:151
StringProperty m_dumpOFCfile
Definition LArOFCAlg.h:123
BooleanProperty m_computePed
Definition LArOFCAlg.h:163
BooleanProperty m_normalize
Definition LArOFCAlg.h:126
BooleanProperty m_isSC
Definition LArOFCAlg.h:172
virtual StatusCode stop()
StringArrayProperty m_keylist
Definition LArOFCAlg.h:124
unsigned int m_nPoints
Definition LArOFCAlg.h:121
LArCaliWaveContainer * m_waveCnt_nc
Definition LArOFCAlg.h:131
LArOFCAlg(const std::string &name, ISvcLocator *pSvcLocator)
Definition LArOFCAlg.cxx:40
StringProperty m_groupingType
Definition LArOFCAlg.h:157
static void optFiltDelta(const std::vector< float > &gWave_in, const std::vector< float > &gDerivWave_in, const Eigen::MatrixXd &autoCorrInv, const Eigen::VectorXd &delta, std::vector< float > &vecOFCa, std::vector< float > &vecOFCb)
IntegerProperty m_nThreads
Definition LArOFCAlg.h:164
void process(perChannelData_t &, const LArOnOffIdMapping *cabling) const
Helper for the Liquid Argon Calorimeter cell identifiers.
Liquid Argon Physics Wave Container.
int getTimeOffset() const
Definition LArPhysWave.h:97
LArWave translate(const LArWave &theWave, int nShift, double baseline=0.) const
LArWave derive_smooth(const LArWave &theWave) const
smoothed derivative
unsigned int getMax(const LArWave &theWave) const
return index of maximum sample
unsigned getStart(const LArWave &theWave) const
size_t getSize() const
number of time samples
Definition LArWave.h:62
bool isEmpty() const
is LArWave uninitialized?
Definition LArWave.h:183
const double & getSample(const unsigned int i) const
Amplitude per time bin.
Definition LArWave.h:53
const double & getDt() const
delta time
Definition LArWave.h:50
unsigned getFlag() const
flag: ...
Definition LArWave.h:178
const std::string process
@ LARNGAIN
Definition CaloGain.h:19
@ LARHIGHGAIN
Definition CaloGain.h:18
std::vector< std::vector< float > > ofcV2_a
Definition LArOFCAlg.h:75
std::vector< std::vector< float > > ofc_b
Definition LArOFCAlg.h:73
std::vector< std::vector< float > > shapeDer
Definition LArOFCAlg.h:79
std::vector< std::vector< float > > ofcV2_b
Definition LArOFCAlg.h:76
std::vector< std::vector< float > > shape
Definition LArOFCAlg.h:78
std::vector< std::vector< float > > ofc_a
Definition LArOFCAlg.h:72
const LArWaveCumul * inputWave
Definition LArOFCAlg.h:67