ATLAS Offline Software
Loading...
Searching...
No Matches
TBECLArRawChannelBuilder.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3*/
4
7
9#include "TBEvent/TBPhase.h"
10
16#include "CLHEP/Units/SystemOfUnits.h"
18#include "AthenaKernel/Units.h"
19
20#include <math.h>
21
22using CLHEP::MeV;
23using CLHEP::megahertz;
24using Athena::Units::picosecond;
25
26TBECLArRawChannelBuilder::TBECLArRawChannelBuilder (const std::string& name, ISvcLocator* pSvcLocator):
27 AthAlgorithm(name, pSvcLocator),
29 m_calo_id(0),
30 m_DataLocation("FREE"),
31 m_ChannelContainerName("LArRawChannels"),
32 m_useTDC(false),
33 m_useRamp(true),
34 m_useShape(true),
36 m_Ecut(256*MeV),
38 m_ramp_max(),
39 m_noEnergy(0),
40 m_noTime(0),
41 m_noShape(0),
42 m_noShapeDer(0),
43 m_saturation(0),
45 m_lastNoTime(0),
49 m_aveNoTime(0),
50 m_aveNoShape(0),
53 m_nEvents(0),
57 m_emId(0),
58 m_adc2mev()
59 //m_NOFCPhases(24),
60 //m_NOFCTimeBins(24)
61 {
62 //m_useIntercept={false,false,false,false};
63 declareProperty("LArRawChannelContainerName",m_ChannelContainerName);
64 declareProperty("DataLocation", m_DataLocation );
65 declareProperty("UseTDC", m_useTDC);
66 declareProperty("UseRamp",m_useRamp);
67 declareProperty("UseShape",m_useShape);
68 declareProperty("ConvertADCToHighGain",m_ConvertADCToHighGain);
69 declareProperty("Ecut", m_Ecut);
70 declareProperty("UseHighGainRampIntercept", m_useIntercept[CaloGain::LARHIGHGAIN]=false);
71 declareProperty("UseMedGainRampIntercept", m_useIntercept[CaloGain::LARMEDIUMGAIN]=false);
72 declareProperty("UseLowGainRampIntercept", m_useIntercept[CaloGain::LARLOWGAIN]=false);
73 declareProperty("InitialTimeSampleShift", m_initialTimeSampleShift);
74 declareProperty("NOFCTimeBins", m_NOFCTimeBins=25); //Number of OFC time bins in a sampling periode
76 declareProperty("NOFCPhases", m_NOFCPhases); //Total number of available OFC sets
77 declareProperty("UseOFCPhase", m_useOFCPhase=false);
78 declareProperty("PhaseInversion", m_phaseInv=false);
79 declareProperty("SamplingPeriod", m_SamplingPeriode=1/(40.08*megahertz));
81 declareProperty("BinHalfOffset", m_binHalfOffset=false);
82 declareProperty("AllowTimeSampleJump", m_allowTimeJump=true);
83 declareProperty("PedestalFallbackMode", m_pedestalFallbackMode=0); // 0=only DB, 1=Only if missing,
84 declareProperty("PedestalSample", m_iPedestal=0); // 2=Low, 3=Low+Me dium, 4=All LAr
85 declareProperty("ShapeMode", m_shapeMode=0);
86 declareProperty("SkipSaturCellsMode", m_skipSaturCells=0);
87 declareProperty("ADCMax", m_AdcMax=4095);
88 declareProperty("HVcorr", m_hvcorr=false);
89}
90
91
93
94 ATH_CHECK( detStore()->retrieve(m_onlineHelper, "LArOnlineID") );
95
96 ATH_CHECK( m_ofcKey.initialize() );
97 ATH_CHECK( m_adc2mevKey.initialize (m_useRamp) );
98
99 if (!m_useRamp)
100 {
101 // pointer to CaloCell ID helper:
102 ATH_CHECK( detStore()->retrieve (m_calo_id, "CaloCell_ID") );
103
104 for (int i=0; i<30; i++) {
105 m_adc2mev[i] = 0;
106 if (i == 6) m_adc2mev[i] = 0.041*637; // EMEC2
107 if (i == 7) m_adc2mev[i] = 0.030*637; // EMEC3
108 if (i == 8) m_adc2mev[i] = 0.00360*3270; // HEC0
109 if (i == 9) m_adc2mev[i] = 0.00380*3270; // HEC1
110 if (i == 10) m_adc2mev[i] = 0.00186*6540; // HEC2
111 if (i == 21 || i == 22) m_adc2mev[i] = 0.1087*767; // FCal1,2
112 if (i == 23) m_adc2mev[i] = 0.1087*1508; // FCal3
113 }
114 }
115
116 // ***
117
118 m_emId=m_calo_id->em_idHelper();
119
120 // translate offline ID into online ID
121 ATH_CHECK( m_cablingKey.initialize() );
122
123 // ***
124
126
127
128 //m_larRawOrdering.setMap(&(*m_roiMap));
129
130 //Set counters for errors and warnings to zero
131 m_noEnergy = 0; // Number of events with at least completly failed channel
132 m_noTime = 0; // Number of events with at least one channel without time info
133 m_noShape = 0; // Number of events with at least one channel without Shape (=with not quality factor);
134 m_noShapeDer = 0; // Number of events with at least one channel without ShapeDerivative (=not taken into accout for quality factor);
135 m_saturation = 0; // Number of events with at least one saturating channel
136
137 m_lastNoEnergy = -1; // Number of completly failed channels in previous event
138 m_lastNoTime = -1; // Number of channels without time info in previous event
139 m_lastNoShape = -1; // Number of channels without Shape (=with not quality factor) in previous event
140 m_lastNoShapeDer = -1; // Number of channels without ShapeDerivative in previous event
141
142 //m_lastSaturCells = -1; // Number of saturating channels without in previous event (not used)
143
144 m_aveNoEnergy = 0.; // Average number of completly failed channels per event
145 m_aveNoTime = 0.; // Average number of channels without time info per event
146 m_aveNoShape = 0.; // Average number of channels without Shape (=with not quality factor) per event
147 m_aveNoShapeDer = 0.; // Average number of channels without ShapeDerivative per event
148 m_aveSaturCells = 0.; // Average number of saturating channels without per event
149
150 m_nEvents = 0 ; // Total number of processed events ;
151 m_aveChannels = 0 ; // Average number of readout channels per event
152
153 if ( m_skipSaturCells > 2 ) m_skipSaturCells = 0 ;
154
158
159 // Validity range for a set of OFC's. If the time shift is larger than this number,
160 // we make a ADC sample jump (e.g. from [0,5] to [1,6]. The second half of the uppermost
161 // bin should already be rounded to the 0th bin of the following ADC sample.
162 if ( m_binHalfOffset ) {
165 } else {
168 }
169
170 ATH_MSG_DEBUG ( "Number of OFC time bins per sampling periode=" << m_NOFCTimeBins );
171 ATH_MSG_DEBUG ( "Sampling Periode=" << m_SamplingPeriode << "ns" );
172 ATH_MSG_DEBUG ( "Sampling Periode Limits: (" << m_SamplingPeriodeLowerLimit
173 << "," << m_SamplingPeriodeUpperLimit << ") ns" );
174
175 return StatusCode::SUCCESS;
176}
177
178
179
180StatusCode TBECLArRawChannelBuilder::execute(const EventContext& ctx)
181{
182
183 //Counters for errors & warnings per event
184 int noEnergy = 0; // Number of completly failed channels in a given event
185 int BadTiming = 0; // Number of channels with bad timing in a given event
186 int noTime = 0; // Number of channels without time info in a given event
187 int noShape = 0; // Number of channels without Shape (= with no quality factor) in a given event
188 int noShapeDer = 0; // Number of channels without ShapeDerivative in a given event
189 int highE = 0; // Number of channels with 'high' (above threshold) energy in a given event
190 int saturation = 0; // Number of saturating channels in a given event
191
192 const ILArHVScaleCorr *oflHVCorr=nullptr;
193 if(m_hvcorr) {
195 oflHVCorr = *oflHVCorrHdl;
196 if(!oflHVCorr) {
197 ATH_MSG_ERROR( "Could not get the HVScaleCorr from key " << m_offlineHVScaleCorrKey.key() );
198 return StatusCode::FAILURE;
199 }
200 }
202 const LArOnOffIdMapping* cabling{*cablingHdl};
203 if(!cabling) {
204 ATH_MSG_ERROR( "Could not get the cabling mapping from key " << m_cablingKey.key() );
205 return StatusCode::FAILURE;
206 }
207
208 //Pointer to input data container
209 const LArDigitContainer* digitContainer=NULL;//Pointer to LArDigitContainer
210 //const TBPhase* theTBPhase; //Pointer to Testbeam TDC-Phase object (if needed)
211 float PhaseTime=0; //Testbeam TDC phase (if needed)
212 float globalTimeOffset=0;
213 //Pointer to conditions data objects
214 const ILArFEBTimeOffset* larFebTimeOffset=NULL;
215 const ILArShape* larShape=NULL;
216 //Retrieve Digit Container
217
218 ATH_CHECK( evtStore()->retrieve(digitContainer,m_DataLocation) );
219
220 //Retrieve calibration data
221 const ILArPedestal* larPedestal=nullptr;
222 ATH_CHECK( detStore()->retrieve(larPedestal) );
223
224 if (m_useShape) {
225 ATH_MSG_DEBUG ( "Retrieving LArShape object" );
226 StatusCode sc=detStore()->retrieve(larShape);
227 if (sc.isFailure()) {
228 ATH_MSG_WARNING ( "Can't retrieve LArShape from Conditions Store" << std::endl
229 << "Quality factor will not be caluclated." );
230 larShape=NULL;
231 }
232 }
233
234 ATH_MSG_DEBUG ( "Retrieving LArOFC object" );
236
237 const LArADC2MeV* adc2mev = nullptr;
238 if (m_useRamp) {
240 adc2mev = *adc2mevH;
241 }
242
243 //retrieve TDC
244 if (m_useTDC) { //All this timing business is only necessary if the readout and the beam are not in phase (Testbeam)
245 const TBPhase* theTBPhase = nullptr;
246 const ILArGlobalTimeOffset* larGlobalTimeOffset = nullptr;
247 ATH_CHECK( evtStore()->retrieve(theTBPhase,"TBPhase") );
248 //Get Phase in nanoseconds
249 PhaseTime = theTBPhase->getPhase();
250 // ###
251 if (m_phaseInv) PhaseTime = m_SamplingPeriode - PhaseTime ;
252 ATH_MSG_DEBUG ( " *** Phase = " << PhaseTime );
253 // ###
254
255 //Get Global Time Offset
256 StatusCode sc=detStore()->retrieve(larGlobalTimeOffset);
257 if (sc.isSuccess()) globalTimeOffset = larGlobalTimeOffset->TimeOffset();
258
259 //Get FEB time offset
260 sc=detStore()->retrieve(larFebTimeOffset);
261 if (sc.isFailure()) larFebTimeOffset=NULL;
262 }
263
264
265 LArRawChannelContainer* larRawChannelContainer=new LArRawChannelContainer();
266 larRawChannelContainer->reserve(digitContainer->size());
267 StatusCode sc = evtStore()->record(larRawChannelContainer,m_ChannelContainerName);
268 if(sc.isFailure()) {
269 ATH_MSG_ERROR ( "Can't record LArRawChannelContainer in StoreGate" );
270 }
271
272 // Average number of LArDigits per event
273 m_nEvents++;
274 m_aveChannels += digitContainer->size();
275
276 bool debugPrint=false;
277 if (msgLvl(MSG::DEBUG) ) debugPrint=true;
278
279 // Now all data is available, start loop over Digit Container
280 int ntot_raw=0;
281
282 for (const LArDigit* digit : *(digitContainer)) {
283
284 //Data that goes into RawChannel:
285 float energy=0;
286 float time=0;
287 float quality=0;
288
289 int OFCTimeBin=0;
290 int timeSampleShift=m_initialTimeSampleShift;
291
292 //Get data from LArDigit
293 const std::vector<short>& samples=digit->samples();
294 const unsigned nSamples=samples.size();
295 const HWIdentifier chid=digit->channelID();
296 const CaloGain::CaloGain gain=digit->gain();
297
298 // to be used in case of DEBUG output
299 int layer = -99999 ;
300 int eta = -99999 ;
301 int phi = -99999 ;
302 int region = -99999 ;
303 if (msgLvl(MSG::DEBUG) ) {
304 Identifier id ;
305 try {
306 id = cabling->cnvToIdentifier(chid);
307 } catch ( LArID_Exception & except ) {
308 ATH_MSG_DEBUG ( "A Cabling exception was caught for channel 0x!"
309 << MSG::hex << chid.get_compact() << MSG::dec );
310 continue ;
311 }
312 layer = m_emId->sampling(id);
313 eta = m_emId->eta(id);
314 phi = m_emId->phi(id);
315 region = m_emId->region(id);
316 ATH_MSG_VERBOSE ( "Channel 0x" << MSG::hex << chid.get_compact() << MSG::dec
317 << " [ Layer = " << layer << " - Eta = " << eta
318 << " - Phi = " << phi << " - Region = " << region << " ] " );
319 }
320
321 // check for saturation, in case skip channel
322 int nSatur=-1 ;
323 for (unsigned iSample=0;iSample<samples.size();iSample++) {
324 if (samples[iSample]>=m_AdcMax) {
325 nSatur++;
326 break ;
327 }
328 }
329 if ( nSatur>-1 ) {
330 msg() << MSG::DEBUG << "Saturation on channel 0x" << MSG::hex << chid.get_compact() << MSG::dec ;
331 saturation++;
332 }
333 if ( m_skipSaturCells && nSatur>-1 ) {
334 msg() << ". Skipping channel." << endmsg;
335 continue; // Ignore this cell, saturation on at least one sample
336 } else if ( nSatur>-1 ) {
337 msg() << "." << endmsg;
338 }
339
340 //Get conditions data for this channel:
341
342 // Pedestal
343 float pedestal=larPedestal->pedestal(chid,gain);
344
345 float pedestalAverage;
346 if (pedestal < (1.0+LArElecCalib::ERRORCODE)) {
347 if( m_pedestalFallbackMode >= 1 ) {
348 ATH_MSG_DEBUG ( "No pedestal found for channel 0x" << MSG::hex << chid.get_compact() << MSG::dec
349 << " Gain " << gain <<". Using time sample " << m_iPedestal );
350 pedestalAverage=samples[m_iPedestal];
351 } else {
352 ATH_MSG_DEBUG ( noEnergy << ". No pedestal found for channel 0x" << MSG::hex << chid.get_compact() << MSG::dec
353 << " [ Layer = " << layer << " - Eta = " << eta << " - Phi = " << phi << " - Region = " << region << " ]"
354 << " Gain = " << gain << ". Skipping channel." );
355 noEnergy++;
356 continue;
357 }
358 } else {
359 if( ( m_pedestalFallbackMode>=2 && gain==CaloGain::LARLOWGAIN ) ||
362 ATH_MSG_DEBUG ( "Forcing pedestal fallback for channel 0x" << MSG::hex << chid.get_compact()
363 << MSG::dec << " Gain=" << gain << ". Using time sample " << m_iPedestal );
364 pedestalAverage=samples[m_iPedestal];
365 } else {
366 pedestalAverage=pedestal;
367 }
368 }
369
370 // Optimal Filtering Coefficients
371 ILArOFC::OFCRef_t ofc_a;
372 ILArOFC::OFCRef_t ofc_b;
373 {// get OFC from Conditions Store
374 float febTimeOffset=0;
375 const HWIdentifier febid=m_onlineHelper->feb_Id(chid);
376 if (larFebTimeOffset)
377 febTimeOffset=larFebTimeOffset->TimeOffset(febid);
378 double timeShift=PhaseTime+globalTimeOffset+febTimeOffset;
379 if (debugPrint)
380 msg() << MSG::VERBOSE << "Channel 0x" << MSG::hex << chid.get_compact() << MSG::dec
381 << " phase=" << PhaseTime << " Feb=" << febTimeOffset
382 << " Global=" << globalTimeOffset;
383
384 if (m_useOFCPhase) {
385 const double ofcTimeOffset=larOFC->timeOffset(chid,gain);
386 timeShift+=ofcTimeOffset;
387 if (debugPrint) msg() << MSG::VERBOSE << " OFC=" << ofcTimeOffset;
388 }
389
390 if (debugPrint) msg() << MSG::VERBOSE << " Total=" << timeShift << endmsg;
391
392 if (m_allowTimeJump && timeShift >= m_NOFCPhases*m_OFCTimeBin ) {
393 if (debugPrint) ATH_MSG_VERBOSE ( "Time Sample jump: -1" );
394 timeSampleShift -= 1;
395 //timeShift -= m_NOFCTimeBins*m_OFCTimeBin ;
396 timeShift -= m_SamplingPeriode ;
397 }
398 else if (m_allowTimeJump && timeShift < 0 ) {
399 if (debugPrint) ATH_MSG_VERBOSE ( "Time Sample jump: +1" );
400 timeSampleShift += 1;
401 //timeShift += m_NOFCTimeBins*m_OFCTimeBin ;
402 timeShift += m_SamplingPeriode ;
403 }
404
405 if (m_allowTimeJump && ( timeShift > m_NOFCPhases*m_OFCTimeBin || timeShift < 0 ) ) {
406 BadTiming++;
407 noEnergy++;
408 ATH_MSG_ERROR ( noEnergy << ". Time offset out of range for channel 0x" << MSG::hex << chid.get_compact() << MSG::dec
409 << " Found " << timeShift << ", expected ( 0 - " << m_NOFCPhases*m_OFCTimeBin << ") ns. Skipping channel." );
410 continue;
411 }
412
413 if (m_allowTimeJump && timeSampleShift < 0) {
414 BadTiming++;
415 noEnergy++;
416 ATH_MSG_ERROR ( noEnergy << ". Negative time sample (" << timeSampleShift << ") shift for channel 0x" << MSG::hex << chid.get_compact() << MSG::dec
417 << " Found. Skipping channel." );
418 continue;
419 }
420
421 OFCTimeBin = (int) ( timeShift / m_OFCTimeBin );
422
423 if ( !m_phaseInv ) // if not done with PhaseTime at the beginning, invert time bin for OFC bin selection
424 OFCTimeBin = ( m_NOFCTimeBins - 1 ) - OFCTimeBin;
425 // do not use the following: 24<PhaseTime<25 you always get OFCTimeBin = -1!
426 //else
427 // OFCTimeBin -= 1 ;
428
429 if (debugPrint) ATH_MSG_VERBOSE ( "OFC bin width = " << m_OFCTimeBin << " - OFCBin = " << OFCTimeBin << " - timeShift = " << timeShift );
430
431 if ( OFCTimeBin < 0 ) {
432 ATH_MSG_ERROR ( "Channel " << MSG::hex << chid.get_compact() << MSG::dec << " asks for OFC bin = " << OFCTimeBin << ". Set to 0." );
433 OFCTimeBin=0;
434 } else if ( OFCTimeBin >= m_NOFCPhases ) {
435 ATH_MSG_ERROR ( "Channel " << MSG::hex << chid.get_compact() << MSG::dec << " asks for OFC bin = " << OFCTimeBin << ". Set to (NOFCPhases-1) =" << m_NOFCTimeBins-1 );
436 OFCTimeBin = m_NOFCPhases-1;
437 }
438
439 ofc_a=larOFC->OFC_a(chid,gain,OFCTimeBin);
440 //ofc_b=&(larOFC->OFC_b(chid,gain,OFCTimeBin)); retrieve only when needed
441 }
442
443 //Check if we have OFC for this channel and time bin
444 if (ofc_a.size()==0) {
445 noEnergy++;
446 ATH_MSG_DEBUG ( noEnergy << ". No OFC's found for channel 0x" << MSG::hex << chid.get_compact() << MSG::dec
447 << " [ Layer = " << layer << " - Eta = " << eta << " - Phi = " << phi << " - Region = " << region << " ]"
448 << " Time bin = " << OFCTimeBin << ", Gain = " << gain << ". Skipping channel." );
449 continue;
450 }
451 if (ofc_a.size()+timeSampleShift>nSamples) {
452 BadTiming++;
453 noEnergy++;
454 if (timeSampleShift==0)
455 ATH_MSG_DEBUG ( "Found LArDigit with " << nSamples << " samples, but OFCs for "
456 << ofc_a.size() << " samples. Skipping Channel ");
457 else //have time sample shift
458 ATH_MSG_DEBUG ( "After time sample shift of " << timeSampleShift << ", " << nSamples-timeSampleShift
459 << " samples left, but have OFCs for " << ofc_a.size() << " samples. Skipping Channel ");
460 continue;
461 }
462
463 //Now apply Optimal Filtering to get ADC peak
464 float ADCPeak=0;
465 for (unsigned i=0;i<(ofc_a.size());i++)
466 ADCPeak+=(samples[i+timeSampleShift]-pedestalAverage)*ofc_a.at(i);
467
468 if (debugPrint) ATH_MSG_VERBOSE ( "ADC Height calculated " << ADCPeak << " TimeBin=" << OFCTimeBin );
469
470 if (m_useRamp) {
471 //ADC2MeV (a.k.a. Ramp)
472 LArVectorProxy ramp = adc2mev->ADC2MEV(chid,gain);
473 //Check ramp coefficents
474 if (ramp.size()==0) {
475 noEnergy++;
476 ATH_MSG_DEBUG ( noEnergy << ". No ADC2MeV data found for channel 0x" << MSG::hex << chid.get_compact() << MSG::dec
477 << " [ Layer = " << layer << " - Eta = " << eta << " - Phi = " << phi << " - Region = " << region << " ]"
478 << " Gain = " << gain << ". Skipping channel." );
479 continue;
480 }
481
482 // temporary fix for bad ramps... should be done in the DB
483 if(ramp[1]>m_ramp_max[gain] || ramp[1]<0) {
484 noEnergy++;
485 ATH_MSG_DEBUG ( "Bad ramp for channel " << chid << " (ramp[1] = " << ramp[1] << "): skip this channel" );
486 continue;
487 }
488
489 float ADCPeakPower=ADCPeak;
490
491 if (m_useIntercept[gain])
492 energy=ramp[0];
493 //otherwise ignore intercept, E=0;
494 for (unsigned i=1;i<ramp.size();i++)
495 {energy+=ramp[i]*ADCPeakPower; //pow(ADCPeak,i);
496 ADCPeakPower*=ADCPeak;
497 }
498 } else {
499 energy = ADCPeak;
501 energy *= 9.5;
502 Identifier id = cabling->cnvToIdentifier(chid);
503 int is = m_calo_id->calo_sample(id);
504 energy *= m_adc2mev[is]; // Ramp for h.g. scale
505 }
506
507// HV correction
508
509 if (m_hvcorr) {
510// HV tool
511 float hvCorr = oflHVCorr-> HVScaleCorr(chid);
512 energy = energy*hvCorr;
513 }
514
515 //Check if energy is above threshold for time & quality calculation
516 if (energy>m_Ecut) {
517 highE++;
518 ofc_b=larOFC->OFC_b(chid,gain,OFCTimeBin);
519 if (ofc_b.size() != ofc_a.size()) {//don't have proper number of coefficients
520 if (ofc_b.size()==0)
521 ATH_MSG_DEBUG ( "No time-OFC's found for channel 0x" << MSG::hex << chid.get_compact() << MSG::dec
522 << " Gain "<< gain << " found. Time not calculated." );
523 else
524 ATH_MSG_DEBUG ( "OFC for time size " << ofc_b.size()
525 << " not equal to OFC for energy size " << ofc_a.size()
526 << " Time not calculated " );
527 noTime++;
528 }else{
529 for (unsigned i=0;i<(ofc_b.size());i++)
530 time+=(samples[i+timeSampleShift]-pedestalAverage)*ofc_b.at(i);
531 time/=ADCPeak;
532 // !! Time is now in ns with respect to calibration pulse shape
533 // Used to calculate quality factor
534 }
535 if (debugPrint) ATH_MSG_VERBOSE ( "Time calculated " << time << " TimeBin=" << OFCTimeBin );
536
537 //Calculate Quality factor
538 if (larShape) { //Have shape object
539 //Get Shape & Shape Derivative for this channel
540
541 //const std::vector<float>& shape=larShape->Shape(chid,gain,OFCTimeBin);
542 //const std::vector<float>& shapeDer=larShape->ShapeDer(chid,gain,OFCTimeBin);
543 // ###
544 ILArShape::ShapeRef_t shape=larShape->Shape(chid,gain,OFCTimeBin,m_shapeMode);
545 ILArShape::ShapeRef_t shapeDer=larShape->ShapeDer(chid,gain,OFCTimeBin,m_shapeMode);
546 // ###
547
548 //Check Shape
549 if (shape.size() < ofc_a.size()) {
550 if (shape.size()==0)
551 ATH_MSG_DEBUG ( "No Shape found for channel 0x" << MSG::hex << chid.get_compact() << MSG::dec
552 << " Gain "<< gain << ". Quality factor not calculated." );
553 else
554 ATH_MSG_DEBUG ( "Shape size " << shape.size()
555 << "smaller than OFC size " << ofc_a.size()
556 << "for channel 0x" << MSG::hex << chid.get_compact()
557 << MSG::dec << ". Quality factor not calculated." );
558 quality=0; //Can't calculate chi^2, assume good hit.
559 noShape++;
560 }
561 else {//Shape ok
562 if (time!=0 && shapeDer.size()!=shape.size()) {
563 //Send warning
564 ATH_MSG_DEBUG ( "Shape-Derivative has different size than Shape for channel 0x" << MSG::hex << chid.get_compact() << MSG::dec
565 << ". Derivative not taken into accout for quality factor." );
566 noShapeDer++;
567 }//end-if
568 if (time==0 || shapeDer.size()!=shape.size() ) { //Calculate Q without time info
569 for (unsigned i=0;i<(ofc_a.size());i++)
570 quality+=((samples[i+timeSampleShift]-pedestalAverage)-shape[i]*ADCPeak)*
571 ((samples[i+timeSampleShift]-pedestalAverage)-shape[i]*ADCPeak);
572 }
573 else { //All input data ok, calculate Q with time info
574 for (unsigned i=0;i<(ofc_a.size());i++)
575 quality+=((samples[i+timeSampleShift]-pedestalAverage)-((shape[i]-shapeDer[i]*time)*ADCPeak))*
576 ((samples[i+timeSampleShift]-pedestalAverage)-((shape[i]-shapeDer[i]*time)*ADCPeak));
577 }
578 } // end else (Shape ok)
579 } //end if larShape
580 else { //No Shape found at all
581 quality=0; //Can't calculate chi^2, assume good hit.
582 noShape++;
583 }
584 // if (m_useTDC) //Correct time according to EMTB definition (do we really want this?)
585 // time= -time+24.5-tbin;
586 }// end-if energy>Ecut
587 else
588 quality=-1; //in case E<Ecut
589 //time*=1000.0;
590 time=time/picosecond; //Convert time to ps
591 //Make LArRawChannel Object with new data
592
593 uint16_t iquality=0;
594 uint16_t iprovenance=0xA5;
595 if (quality>=0) {
596 iquality = ((int)(quality) ) & 0xFFFF;
597 iprovenance=iprovenance | 0x2000;
598 }
599
600
601 LArRawChannel larRawChannel(chid,(int)energy,(int)time,iquality,iprovenance, gain);
602 larRawChannelContainer->push_back(larRawChannel); //Add to container
603 ntot_raw++;
604 if (debugPrint)
605 ATH_MSG_VERBOSE ( "Got LArRawChannel #" << ntot_raw << ", chid=0x" << MSG::hex << chid.get_compact() << MSG::dec
606 << " e=" << energy << " t=" << time << " Q=" << quality );
607 } // End loop over LArDigits
608
609 ATH_MSG_DEBUG ( ntot_raw << " channels successfully processed, (" << highE << " with high energy)" );
610
611 // deal with bad timing
612 if(BadTiming>=128){
613 ATH_MSG_ERROR ( "Too many channels (" <<BadTiming<< " !) have a bad timing !!" );
614 ATH_MSG_ERROR ( "OFC time constants should be revisited !!!" );
615 ATH_MSG_ERROR ( "Event is skipped" );
616 larRawChannelContainer->clear();
617 //return StatusCode::SUCCESS;
618 }
619
620 // in case of at least one saturating cell, skip all event (if selected)
621 if ( saturation && m_skipSaturCells == 2 ) {
622 ATH_MSG_ERROR ( saturation << " saturating channels were found. Event is skipped." );
623 larRawChannelContainer->clear();
624 }
625
626 //Put this LArRawChannel container in the transient store
627 //sc = evtStore()->record(m_larRawChannelContainer, m_ChannelContainerName);
628 //if(sc.isFailure()) {
629 // log << MSG::ERROR << "Can't record LArRawChannelContainer in StoreGate" << endmsg;
630 //}
631 //else
632 // std::cout << "Successfully recorded LArRawChannelContainer to StoreGate" << std::endl;
633
634 /*
635
636 Error & Warning summary *per event*
637
638 Strategy: 'No Energy' is an ERROR, no time or no quality is a WARNING
639
640 Missing calibration constants are most likly missing for an entire run, threfore:
641 In DEBUG: Print summary for each event if something is missing
642 otherwise: Print summary only for new problems (different number of missing channels)
643
644 Saturatin cells summary is shown in any case, WARNING if not skipped, ERROR if skipped
645
646 */
647
648 if (noEnergy) m_noEnergy++;
649 if (noTime) m_noTime++;
650 if (noShape) m_noShape++;
651 if (noShapeDer) m_noShapeDer++;
652 if (saturation) m_saturation++;
653
654 m_aveNoEnergy += noEnergy;
655 m_aveNoTime += noTime;
656 m_aveNoShape += noShape;
657 m_aveNoShapeDer += noShapeDer;
658 m_aveSaturCells += saturation;
659
660 if ( ( noEnergy!=m_lastNoEnergy
661 || noTime!=m_lastNoTime
662 || noShape>m_lastNoShape
663 || noShapeDer>m_lastNoShapeDer
664 || saturation>0 )
665 || ( msgSvc()->outputLevel(name()) <= MSG::DEBUG && ( noEnergy || noTime || noShape || noShapeDer || saturation ) )
666 ) {
667
668 m_lastNoEnergy = noEnergy;
669 m_lastNoTime = noTime;
670 if (noShape>m_lastNoShape) m_lastNoShape=noShape;
671 if (noShapeDer>m_lastNoShapeDer) m_lastNoShapeDer=noShapeDer;
672 //m_lastSaturCells = saturation ;
673
674 MSG::Level msglvl;
675 if (noEnergy)
676 msglvl=MSG::ERROR;
677 else
678 msglvl=MSG::WARNING;
679 msg() << msglvl << " *** Error & Warning summary for this event *** " << std::endl;
680
681 if ( noEnergy ) {
682 msg() << msglvl << " " << noEnergy << " out of "
683 << digitContainer->size() << " channel(s) skipped due to a lack of basic calibration constants."
684 << std::endl;
685 }
686 if ( noTime ) {
687 msg() << msglvl << " " << noTime << " out of "
688 << highE << " high-enegy channel(s) have no time-info due to a lack of Optimal Filtering Coefficients."
689 << std::endl;
690 }
691 if ( noShape ) {
692 msg() << msglvl << " " << noShape << " out of "
693 << highE << " high-enegy channel(s) have no quality factor due to a lack of shape."
694 << std::endl;
695 }
696 if ( noShapeDer ) {
697 msg() << msglvl << " " << noShapeDer << " out of "
698 << highE << " high-enegy channel(s) lack the derivative of the shape. Not taken into accout for Quality factor."
699 << std::endl;
700 }
701 if ( saturation ) {
702 if ( m_skipSaturCells == 2 )
703 msg() << MSG::ERROR << " " << saturation << " out of "
704 << digitContainer->size() << " channel(s) showed saturations. The complete event was skipped." << std::endl;
705 else if ( m_skipSaturCells == 1 )
706 msg() << MSG::ERROR << " " << saturation << " out of "
707 << digitContainer->size() << " channel(s) showed saturations and were skipped." << std::endl;
708 else
709 msg() << MSG::WARNING << " " << saturation << " out of "
710 << digitContainer->size() << " channel(s) showed saturations." << std::endl;
711 }
712 msg() << endmsg;
713 }
714
715 // lock raw channel container
716 ATH_CHECK( evtStore()->setConst(larRawChannelContainer) );
717
718 return StatusCode::SUCCESS;
719}
720
722{
723
729
731
732 // Error and Warning Summary for this job:
733
734 ATH_MSG_DEBUG ( " TBECLArRawChannelBuilder::finalize "
735 << m_noEnergy << " " << m_noTime << " " << m_noShape << " " << m_noShapeDer << " " << m_saturation );
736
738 MSG::Level msglvl;
740 msglvl=MSG::ERROR;
741 else
742 msglvl=MSG::WARNING;
743 msg() << msglvl << " *** Error & Warning Summary for all events *** " << std::endl ;
744
745 if (m_noEnergy)
746 msg() << msglvl << " " << m_noEnergy << " events had on average " << (int)round(m_aveNoEnergy)
747 << " channels out of " << (int)round(m_aveChannels) << " without basic calibration constants."
748 << std::endl;
749
750 if (m_noTime)
751 msg() << msglvl << " " << m_noTime << " events had on average " << (int)round(m_aveNoTime)
752 << " channels out of " << (int)round(m_aveChannels) << " without OFCs for timing."
753 << std::endl ;
754
755 if (m_noShape)
756 msg() << msglvl << " " << m_noShape << " events had on average " << (int)round(m_aveNoShape)
757 << " channels out of " << (int)round(m_aveChannels) << " without shape information."
758 << std::endl;
759
760 if (m_noShapeDer)
761 msg() << msglvl << " " << m_noShapeDer << " events had on average " << (int)round(m_aveNoShapeDer)
762 << " channels out of " << (int)round(m_aveChannels) << " without shape derivative."
763 << std::endl;
764
765 if ( m_saturation )
766 msg() << msglvl << " " << m_saturation << " events had on average " << (int)round(m_aveSaturCells)
767 << " out of " << (int)round(m_aveChannels) << " saturating channels."
768 << std::endl ;
769
770 msg() << endmsg;
771 }
772 else
773 ATH_MSG_INFO ( "TBECLArRawChannelBuilder finished without errors or warnings." );
774
775 //if (m_larRawChannelContainer) {
776 //m_larRawChannelContainer->release();
777 //m_larRawChannelContainer = 0;
778 //}
779
780 return StatusCode::SUCCESS;
781}
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
#define endmsg
#define ATH_CHECK
Evaluate an expression and check for errors.
#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 const double MeV
static Double_t sc
Athena::TPCnvVers::Current Athena::TPCnvVers::Old Athena::TPCnvVers::Old LArRawChannelContainer
Definition LArTPCnv.cxx:86
Wrapper to avoid constant divisions when using units.
AthAlgorithm(const std::string &name, ISvcLocator *pSvcLocator)
Constructor.
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
ServiceHandle< StoreGateSvc > & evtStore()
const ServiceHandle< StoreGateSvc > & detStore() const
bool msgLvl(const MSG::Level lvl) const
size_type size() const noexcept
Returns the number of elements in the collection.
virtual float TimeOffset(const HWIdentifier fId) const =0
virtual float TimeOffset() const =0
LArVectorProxy OFCRef_t
This class defines the interface for accessing Optimal Filtering coefficients for each channel provid...
Definition ILArOFC.h:26
virtual float pedestal(const HWIdentifier &id, int gain) const =0
LArVectorProxy ShapeRef_t
This class defines the interface for accessing Shape (Nsample variable, Dt = 25 ns fixed) @stereotype...
Definition ILArShape.h:26
virtual ShapeRef_t Shape(const HWIdentifier &id, int gain, int tbin=0, int mode=0) const =0
virtual ShapeRef_t ShapeDer(const HWIdentifier &id, int gain, int tbin=0, int mode=0) const =0
value_type get_compact() const
Get the compact id.
const LArVectorProxy ADC2MEV(const HWIdentifier &id, int gain) const
Definition LArADC2MeV.h:32
Container class for LArDigit.
Liquid Argon digit base class.
Definition LArDigit.h:25
Exception class for LAr Identifiers.
Container for LArRawChannel (IDC using LArRawChannelCollection).
Liquid Argon ROD output object base class.
Proxy for accessing a range of float values like a vector.
value_type at(size_t i) const
Vector indexing with bounds check.
SG::ReadCondHandleKey< LArADC2MeV > m_adc2mevKey
SG::ReadCondHandleKey< ILArHVScaleCorr > m_offlineHVScaleCorrKey
virtual StatusCode finalize() override
SG::ReadCondHandleKey< ILArOFC > m_ofcKey
Property: OFC coefficients (conditions input).
SG::ReadCondHandleKey< LArOnOffIdMapping > m_cablingKey
virtual StatusCode execute(const EventContext &ctx) override
Execute method.
TBECLArRawChannelBuilder(const std::string &name, ISvcLocator *pSvcLocator)
virtual StatusCode initialize() override
float getPhase() const
Definition TBPhase.h:42
@ LARMEDIUMGAIN
Definition CaloGain.h:18
@ LARLOWGAIN
Definition CaloGain.h:18
@ LARHIGHGAIN
Definition CaloGain.h:18