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