ATLAS Offline Software
Loading...
Searching...
No Matches
LArPhysWaveShifter.cxx
Go to the documentation of this file.
1//Dear emacs, this is -*- c++ -*-
2
3/*
4 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
5*/
6
7
11#include "GaudiKernel/ToolHandle.h"
12
14
15#include <iostream>
16#include <fstream>
17#include <string>
18
20
21LArPhysWaveShifter::LArPhysWaveShifter (const std::string& name, ISvcLocator* pSvcLocator)
22: AthAlgorithm(name, pSvcLocator),
23 m_onlineHelper(nullptr),
24 m_larFEBTstart(nullptr),
25 m_groupingType("ExtendedSubDetector") // SubDetector, Single, FeedThrough
26{
27 // Input contaners' keys
28 m_keylist.clear() ;
29 declareProperty("KeyList", m_keylist);
30
31 // Output container key
32 declareProperty("KeyOutput", m_keyout = "LArPhysWave");
33
34 //
35 // Steering options to compute time shifts per FEB (whatever the gain)
36 //
37 declareProperty("ComputeTimeShiftByFEB", m_compTimeShiftByFEB = false) ;
38 declareProperty("TimeShiftByFEBMode", m_modeTimeShiftByFEB = 3) ;
39 declareProperty("TimeShiftByFEBDump", m_dumpTimeShiftByFEB = false) ;
40 declareProperty("TimeShiftByFEBDumpFile", m_fileTimeShiftByFEB = "TimeShiftFEB.py") ;
41
42 //
43 // Time shift modes
44 //
45 declareProperty("TimeShiftByIndex" , m_timeShiftByIndex = 0);
46 declareProperty("TimeShiftByHelper", m_timeShiftByHelper = false);
47
48 declareProperty("TimeShiftFromPeak" , m_timeShiftFromPeak = false) ;
49 declareProperty("NindexFromPeak" , m_nIndexFromPeak = 0, "Number of data points before the peak") ;
50 declareProperty("Ndelays", m_nDelays = 24, "Number of Delay steps between two ADC samples");
51 declareProperty("Nsamplings", m_nSamplings = 3, "Number of ADC samples before the peak");
52
53 declareProperty("TimeShiftByFEB" , m_timeShiftByFEB = false) ;
54 declareProperty("TimeShiftGuardRegion" , m_timeShiftGuardRegion = 0 ) ;
55
56 declareProperty("UsePhysCaliTdiff", m_usePhysCaliTdiff = true);
57
58 declareProperty("TimeShiftOffset", m_timeShiftOffset = false);
59 declareProperty("TimeShiftOffsetValue", m_timeShiftOffsetValue = 0.);
60
61 // Grouping type
62 declareProperty("GroupingType", m_groupingType);
63
64 declareProperty("OutputShiftsKey", m_totalShiftsKey);
65 declareProperty("CellByCellShiftsKey", m_cellByCellShiftsKey);
66
67 declareProperty("isSC",m_isSC=false);
68
69}
70
72= default;
73
75 ATH_MSG_INFO( "... in stop()" ) ;
76
77 LArWaveHelper larWaveHelper;
78
79 // get LArOnlineID helper
80 /*StatusCode sc = detStore()->retrieve(m_onlineHelper, "LArOnlineID");
81 if (sc.isFailure()) {
82 ATH_MSG_ERROR( "Could not get LArOnlineID" );
83 return sc;
84 }*/
85 StatusCode sc;
86 if ( m_isSC ) {
87 const LArOnline_SuperCellID* ll;
88 sc = detStore()->retrieve(ll, "LArOnline_SuperCellID");
89 if (sc.isFailure()) {
90 msg(MSG::ERROR) << "Could not get LArOnlineID helper !" << endmsg;
91 return StatusCode::FAILURE;
92 }
93 else {
94 m_onlineHelper = static_cast<const LArOnlineID_Base*>(ll);
95 ATH_MSG_DEBUG("Found the LArOnlineID helper");
96 }
97 } else { // m_isSC
98 const LArOnlineID* ll;
99 sc = detStore()->retrieve(ll, "LArOnlineID");
100 if (sc.isFailure()) {
101 msg(MSG::ERROR) << "Could not get LArOnlineID helper !" << endmsg;
102 return StatusCode::FAILURE;
103 }
104 else {
105 m_onlineHelper = static_cast<const LArOnlineID_Base*>(ll);
106 ATH_MSG_DEBUG(" Found the LArOnlineID helper. ");
107 }
108 }
109
110 // Retrieve LArPhysWaveTool
111 ToolHandle<LArPhysWaveTool> larPhysWaveTool("LArPhysWaveTool");
112 sc=larPhysWaveTool.retrieve();
113 if (sc!=StatusCode::SUCCESS) {
114 ATH_MSG_ERROR( " Can't get LArPhysWaveTool " );
115 return sc;
116 }
117
118 // retrieve PhysCaliTdiff
119 const ILArPhysCaliTdiff* larPhysCaliTdiff = nullptr;
120 if (m_usePhysCaliTdiff) {
121 sc = detStore()->retrieve(larPhysCaliTdiff,m_cellByCellShiftsKey);
122 if (sc!=StatusCode::SUCCESS) {
123 ATH_MSG_WARNING( "Cannot retrieve LArPhysCaliTdiff with key " << m_cellByCellShiftsKey
124 << ". Disabling use of PhysCaliTdiff values in wave shift." );
125 m_usePhysCaliTdiff = false;
126 }else {
127 ATH_MSG_INFO( "LArPhysCaliTdiff successfully retrieved" );
128 }
129 }
130
131 // compute FEB time shifts
132 if ( m_compTimeShiftByFEB ) {
135 if(!sc.isSuccess()) {
136 ATH_MSG_ERROR( "Can't compute time shifts by FEB." );
137 return sc;
138 }
139 }
140
141 // apply time shifts
142 if ( m_timeShiftByHelper ) {
143 ATH_MSG_INFO( "Will use helper class for start time." );
145 m_timeShiftFromPeak = false ;
146 m_timeShiftByFEB = false ;
147 }
148
149 if ( m_timeShiftByIndex != 0 ) {
150 ATH_MSG_INFO( "Manually shifting pulses by time index " << m_timeShiftByIndex );
151 m_timeShiftFromPeak = false ;
152 m_timeShiftByFEB = false ;
153 }
154
155 if ( m_timeShiftFromPeak ) {
156 ATH_MSG_INFO( "Manually shifting pulses by a constant index from peak." );
158 m_timeShiftByFEB = false ;
159 }
160
161 if (m_timeShiftOffset) {
162 m_timeShiftOffsetValue = m_timeShiftOffsetValue>0. ? (float)((long)(m_timeShiftOffsetValue+0.5)) : (float)((long)(m_timeShiftOffsetValue-0.5)); // round to nearest signed integer
163 if (m_timeShiftOffsetValue <= -999. || m_timeShiftOffsetValue >= 999.) m_timeShiftOffsetValue = 0.; // avoid clearly nonsense values
164 }
165
166 /*
167 Apply FEB time shifts:
168 - can be conputed in the same job...
169 - ...or simply read from DetStore (and leaded either from DB of jobOption using LArEventTest/FakeLArTimeOffset
170 */
171 const ILArFEBTimeOffset* larFebTshift = nullptr;
172 if ( m_timeShiftByFEB ) {
173 ATH_MSG_INFO( "Manually shifting pulses by *FEB* time indexes." );
174 sc = detStore()->retrieve(larFebTshift);
175 if (sc.isFailure()) {
176 ATH_MSG_ERROR( "Cannot find any FEB time offsets. Please check." );
177 return sc;
178 }
179 }
180
181 //New TPhysCaliTimeDiff Container to store the final shift
182 //LArPhysCaliTdiffComplete* totalShifts=new LArPhysCaliTdiffComplete();
183 auto totalShifts = std::make_unique<LArOFCBinComplete>();
184 if (totalShifts->setGroupingType(m_groupingType,msg()).isFailure()) {
185 ATH_MSG_ERROR( "Failed to set grouping type for LArPhysCaliTdiffComplete object" );
186 return StatusCode::FAILURE;
187 }
188
189 if(totalShifts->initialize().isFailure()) {
190 ATH_MSG_ERROR( "Failed to initialize LArPhysCaliTdiffComplete object" );
191 return StatusCode::FAILURE;
192 }
193
194
195 // Get the physics waveforms from the detector store
196 const LArPhysWaveContainer* larPhysWaveContainerOld;
197
198 int nchannel = 0 ;
199
200 for (const std::string& key : m_keylist) { // Loop over all containers that are to be processed
201
202 sc= detStore()->retrieve(larPhysWaveContainerOld,key);
203 if (sc.isFailure()) {
204 ATH_MSG_INFO( "LArPhysWaveContainer (key=" << key << ") not found in StoreGate" );
205 continue ;
206 }
207 ATH_MSG_INFO( "Processing LArPhysWaveContainer from StoreGate, key = " << key );
208
209 // loop over physwave in 'old' container
210 for ( unsigned gain = CaloGain::LARHIGHGAIN ; gain < CaloGain::LARNGAIN; gain++ ) { // Loop over all gains
211
212 // get iterator for all channels for a gain
213 PhysWaveIt wave_it = larPhysWaveContainerOld->begin(gain);
214 PhysWaveIt wave_it_e = larPhysWaveContainerOld->end(gain);
215
216 if ( wave_it == wave_it_e ) {
217 ATH_MSG_INFO( "LArPhysWaveContainer (key = " << key << ") has no wave with gain = " << gain );
218 continue; // skip to next gain
219 }
220
221 for ( ; wave_it!=wave_it_e; wave_it++) {
222
223 if ( nchannel < 100 || ( nchannel < 1000 && nchannel%100==0 ) || nchannel%1000==0 )
224 ATH_MSG_INFO( "Processing physics waveform number " << nchannel );
225 nchannel++ ;
226
227 const LArPhysWave* larPhysWave = &(*wave_it);
228 const HWIdentifier chid = wave_it.channelId();
229
230 if ( larPhysWave->isEmpty() ) {
231 ATH_MSG_VERBOSE("Channel 0x" << MSG::hex << chid.get_compact() << MSG::dec << " is empty. Skipping.");
232 continue;
233 }
234
235 float tstart = 0 ;
236
237 if ( m_timeShiftByHelper ) {
238 tstart = larWaveHelper.getStart(*larPhysWave) ;
239 tstart -= m_timeShiftGuardRegion ;
240 }
241
242 if ( m_timeShiftByIndex != 0 ) {
243 tstart = m_timeShiftByIndex;
244 }
245
246 if ( m_timeShiftFromPeak ) {
247 tstart = larWaveHelper.getMax(*larPhysWave)-m_nIndexFromPeak;
248 }
249
250 if ( m_timeShiftByFEB ) {
251 const HWIdentifier febid = m_onlineHelper->feb_Id(chid);
252 tstart = (int)larFebTshift->TimeOffset(febid);
253 tstart -= m_timeShiftGuardRegion ;
254 }
255
256 if (m_usePhysCaliTdiff && larPhysCaliTdiff) {
257 float tdiff = larPhysCaliTdiff->Tdiff(chid,gain);
258 if (tdiff<=-999.) tdiff = 0.;
259 tdiff /= (25./24.); // in units of delay steps
260 tdiff = tdiff>0. ? (float)((long)(tdiff+0.5)) : (float)((long)(tdiff-0.5)); // round to nearest signed integer
261 ATH_MSG_VERBOSE("Channel 0x" << MSG::hex << chid.get_compact() << MSG::dec << " -> Tdiff = " << tdiff);
262 tstart -= tdiff; // subtract to tstart (should be used on top of timeShiftByFEB)
263 }
264
265 if (m_timeShiftOffset) {
266 tstart -= m_timeShiftOffsetValue;
267 }
268
269 totalShifts->set(chid,gain,(int)(tstart));
270
271 ATH_MSG_VERBOSE("PhysWave n. " << nchannel
272 << " --> Time shift for channel 0x" << MSG::hex << chid.get_compact() << MSG::dec
273 << " is " << tstart << " samples (" << tstart*larPhysWave->getDt() << " ns)");
274
275 /*
276 // apply time shift
277 LArPhysWave newLArPhysWave( (larWaveHelper.translate(*larPhysWave,-tstart,0)).getWave() ,
278 larPhysWave->getDt(),
279 larPhysWave->getFlag() ) ;
280
281
282 // save time shift in new LArPhysWave
283 if ( m_timeShiftByFEB ) {
284 // We save the timeShiftGuardRegion so that, when running
285 // the OFC iteration reconstruction, we can use it in
286 // association to the final phase to compute an absolute
287 // time with respect to the FEB "zero" time, defined as
288 // the peak time of the fastest pulse in the FEB
289 // -- Marco Delmastro and Guillaume Unal, June 2009
290 newLArPhysWave.setTimeOffset(-m_timeShiftGuardRegion);
291 } else {
292 newLArPhysWave.setTimeOffset(tstart);
293 }
294
295 // Add 'new' physics wave to 'new' container
296 larPhysWaveContainerNew->setPdata(chid, newLArPhysWave, gain);
297
298 // Clean the 'old' physics wave from memory (ok, not that elegant, but still...)
299 //LArPhysWave* oldLArPhysWave = const_cast<LArPhysWave*>(larPhysWave);
300 //oldLArPhysWave->clear(); // clear() method is (still) not implemeted on LArWave...
301 */
302 } // end loop over cells
303 } // end of loop over gains
304
305 } // End loop over all PhysWave containers in m_keylist
306
307
308 if (!m_totalShiftsKey.empty()) {
309 sc=detStore()->record(std::move(totalShifts),m_totalShiftsKey);
310 if (sc.isFailure()) {
311 ATH_MSG_ERROR( "Failed to recrod LArPhysCaliTdiffComplete with key " << m_totalShiftsKey );
312 }
313 }
314
315 ATH_MSG_INFO( "LArPhysWaveShifter stopped!" );
316
317 return StatusCode::SUCCESS;
318}
319
320
322{
323 StatusCode sc ;
324
325 LArWaveHelper larWaveHelper;
326
327 // This is to *compute* the smaller time shifts by FEB
329 m_larFEBTstart->setDefaultReturnValue(999);
330 if (mode==3) {
331 std::vector<HWIdentifier>::const_iterator it = m_onlineHelper->feb_begin();
332 std::vector<HWIdentifier>::const_iterator it_e = m_onlineHelper->feb_end();
333 for (;it!=it_e;++it)
334 m_larFEBTstart->setTimeOffset(*it,0);
335 }
336
337 // This is a counter to compute the average time shift per FEB
338 LArFEBTimeOffset nChanInFEB;
339 nChanInFEB.setDefaultReturnValue(0);
340
341 // Get the physics waveforms from the detector store
342 const LArPhysWaveContainer* larPhysWaveContainerOld;
343
344 for (const std::string& key : m_keylist) { // Loop over all containers that are to be processed
345
346 sc=detStore()->retrieve(larPhysWaveContainerOld,key);
347 if (sc.isFailure()) {
348 ATH_MSG_INFO( "LArPhysWaveContainer (key=" << key << ") not found in StoreGate" );
349 continue ;
350 }
351 if ( larPhysWaveContainerOld == nullptr ) {
352 ATH_MSG_INFO( "LArPhysWaveContainer (key=" << key << ") is empty" );
353 continue ;
354 }
355
356 ATH_MSG_INFO( "ComputeTimeShiftByFEB(): processing LArPhysWaveContainer from StoreGate, key = " << key );
357
358 for ( unsigned gain = CaloGain::LARHIGHGAIN ; gain < CaloGain::LARNGAIN; gain++ ) { // Loop over all gains
359
360 PhysWaveIt wave_it = larPhysWaveContainerOld->begin(gain);
361 PhysWaveIt wave_it_e = larPhysWaveContainerOld->end(gain);
362
363 if ( wave_it == wave_it_e ) {
364 ATH_MSG_INFO( "ComputeTimeShiftByFEB(): LArPhysWaveContainer (key = " << key << ") has no wave with gain = " << gain );
365 continue; // skip to next gain
366 }
367
368 for ( ; wave_it!=wave_it_e; wave_it++) {
369
370 const LArPhysWave* larPhysWave = &(*wave_it);
371 if ( larPhysWave->isEmpty() ) continue;
372
373 const HWIdentifier chid = wave_it.channelId();
374 const HWIdentifier febid = m_onlineHelper->feb_Id(chid);
375
376 unsigned oldFEBTstart = (unsigned)m_larFEBTstart->TimeOffset(febid);
377 unsigned newFEBTstart = 999;
378 unsigned theChanInFEB = 0;
379 float bindiff = 0.;
380
381 switch (mode) {
382 case 1 :
383 newFEBTstart = (unsigned)larWaveHelper.getStart(*larPhysWave);
384 if ( newFEBTstart < oldFEBTstart ) m_larFEBTstart->setTimeOffset(febid,newFEBTstart);
385 break;
386 case 2:
387 newFEBTstart = (unsigned)(larWaveHelper.getMax(*larPhysWave)-m_nIndexFromPeak);
388 if ( newFEBTstart < oldFEBTstart ) m_larFEBTstart->setTimeOffset(febid,newFEBTstart);
389 break;
390 case 3:
391 bindiff = larWaveHelper.getMax(*larPhysWave)-m_nIndexFromPeak;
392 ATH_MSG_VERBOSE(std::hex << chid << std::dec<< " TimeOffset: "<<bindiff);
393 if(bindiff >0.)
394 newFEBTstart = (unsigned)(bindiff);
395 else
396 newFEBTstart = 0;
397 m_larFEBTstart->setTimeOffset(febid,oldFEBTstart+newFEBTstart); // accumulate offsets per FEB
398 theChanInFEB = static_cast<unsigned>(nChanInFEB.TimeOffset(febid)+1);
399 nChanInFEB.setTimeOffset(febid,theChanInFEB); // increment channel counter;
400 break;
401 default:
402 newFEBTstart = 0;
403 break;
404 }
405
406 } // end loop over cells
407
408 } // end of loop over gains
409
410 } // end loop over all PhysWave containers in m_keylist
411
412 if ( m_larFEBTstart->size()>0) {
413
414 std::vector<HWIdentifier>::const_iterator it = m_onlineHelper->feb_begin();
415 std::vector<HWIdentifier>::const_iterator it_e = m_onlineHelper->feb_end();
416 unsigned int nFeb=0;
417 for (;it!=it_e;++it) {
418 if ( (int)m_larFEBTstart->TimeOffset(*it) != 999 ) {
419 nFeb++;
420 if ( mode==3 && nChanInFEB.TimeOffset(*it) ) { // average time offset
421 float timeoff = m_larFEBTstart->TimeOffset(*it)/nChanInFEB.TimeOffset(*it);
422 m_larFEBTstart->setTimeOffset(*it,timeoff);
423 }
424 ATH_MSG_INFO( nFeb << ". FEB ID 0x" << std::hex << (*it).get_compact() << std::dec
425 << " - Tstart = " << (int)m_larFEBTstart->TimeOffset(*it) ) ;
426
427 } else {
428 m_larFEBTstart->setTimeOffset(*it,0);
429 }
430
431 }
432
433 if ( m_dumpTimeShiftByFEB ) {
434 std::fstream outfile ;
435 outfile.open("TimeShiftFEB.py",std::ios::out) ;
436 outfile << "FakeLArTimeOffset.FEBids = [ " ;
437 it = m_onlineHelper->feb_begin();
438 unsigned i=0;
439 for (;it!=it_e;++it) {
440 outfile << "0x" << std::hex << (*it).get_compact() << std::dec ;
441 i++ ;
442 if ( i<nFeb ) outfile << ", " ;
443 }
444 outfile << " ]" << std::endl ;
445 outfile << "FakeLArTimeOffset.FEbTimeOffsets = [ " ;
446 it = m_onlineHelper->feb_begin();
447 i = 0 ;
448 for (;it!=it_e;++it) {
449 outfile << (int)m_larFEBTstart->TimeOffset(*it) ;
450 i++ ;
451 if ( i<nFeb ) outfile << ", " ;
452 }
453 outfile << " ]" << std::endl ;
454 outfile.close() ;
455 ATH_MSG_INFO( "Minimum Tstart per FEB (all gain) saved in " << m_fileTimeShiftByFEB ) ;
456 }
457
458 } else {
459 return StatusCode::FAILURE;
460 }
461
462 sc=detStore()->record(m_larFEBTstart,"FebTimeOffset");
463 if(sc.isFailure()) {
464 ATH_MSG_ERROR( "Can't record LArFEBTimeOffset to DetectorStore" );
465 return StatusCode::FAILURE;
466 }
467
468 const ILArFEBTimeOffset* ilarFEBTimeOffset=nullptr;
469 sc=detStore()->symLink(m_larFEBTstart,ilarFEBTimeOffset);
470 if(sc.isFailure()) {
471 ATH_MSG_ERROR( "Can't symlink LArFEBTimeOffset to abstract interface in DetectorStore" );
472 return StatusCode::FAILURE;
473 }
474
475 return StatusCode::SUCCESS;
476}
#define endmsg
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
static Double_t sc
LArPhysWaveContainer::ConstConditionsMapIterator PhysWaveIt
AthAlgorithm(const std::string &name, ISvcLocator *pSvcLocator)
Constructor with parameters:
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
const ServiceHandle< StoreGateSvc > & detStore() const
MsgStream & msg() const
virtual float TimeOffset(const HWIdentifier fId) const =0
virtual const float & Tdiff(const HWIdentifier &id, int gain) const =0
value_type get_compact() const
Get the compact id.
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
float TimeOffset(const HWIdentifier fId) const
void setDefaultReturnValue(const float value)
void setTimeOffset(const HWIdentifier fId, const float offset)
Helper for the Liquid Argon Calorimeter cell identifiers.
Liquid Argon Physics Wave Container.
std::string m_cellByCellShiftsKey
StatusCode ComputeTimeShiftByFEB(unsigned mode)
const LArOnlineID_Base * m_onlineHelper
std::vector< std::string > m_keylist
LArPhysWaveShifter(const std::string &name, ISvcLocator *pSvcLocator)
std::string m_fileTimeShiftByFEB
LArFEBTimeOffset * m_larFEBTstart
unsigned int getMax(const LArWave &theWave) const
return index of maximum sample
unsigned getStart(const LArWave &theWave) const
bool isEmpty() const
is LArWave uninitialized?
Definition LArWave.h:183
const double & getDt() const
delta time
Definition LArWave.h:50
@ LARNGAIN
Definition CaloGain.h:19
@ LARHIGHGAIN
Definition CaloGain.h:18