ATLAS Offline Software
Loading...
Searching...
No Matches
LArRawChannelBuilderSCAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3*/
4
6#include "GaudiKernel/SystemOfUnits.h"
13#include <cmath>
14
15
17 ATH_CHECK(m_digitKey.initialize());
18 ATH_CHECK(m_cellKey.initialize());
19 ATH_CHECK(m_pedestalKey.initialize());
20 ATH_CHECK(m_adc2MeVKey.initialize());
21 ATH_CHECK(m_ofcKey.initialize());
22 ATH_CHECK(m_shapeKey.initialize());
23 ATH_CHECK(m_cablingKey.initialize() );
25
26 ATH_CHECK(detStore()->retrieve(m_onlineId,"LArOnline_SuperCellID"));
27 ATH_CHECK(m_caloSuperCellMgrKey.initialize());
28
29 return StatusCode::SUCCESS;
30}
31
33 return StatusCode::SUCCESS;
34}
35
36StatusCode LArRawChannelBuilderSCAlg::execute(const EventContext& ctx) const {
37
38 //Get event inputs from read handles:
40
41 //Write output via write handle
42 auto outputContainerCellPtr = std::make_unique<CaloCellContainer>(SG::VIEW_ELEMENTS);
43
44 DataPool<CaloCell> dataPool(ctx);
45 unsigned int hash_max = m_onlineId->channelHashMax();
46 if (dataPool.allocated()==0){
47 dataPool.reserve (hash_max);
48 }
49 outputContainerCellPtr->reserve( hash_max );
50
51
52 //Get Conditions input
54 const ILArPedestal* peds=*pedHdl;
55
57 const LArADC2MeV* adc2MeVs=*adc2mevHdl;
58
60 const ILArOFC* ofcs=*ofcHdl;
61
63 const ILArShape* shapes=*shapeHdl;
64
66
68 const CaloSuperCellDetDescrManager* caloMgr = *caloSuperCellMgrHandle;
69
70 const LArBadChannelCont* badchannel(nullptr);
71 if( !m_bcContKey.empty() ){
73 badchannel = *larBadChan;
74 }
75
76 //Loop over digits:
77 for (const LArDigit* digit : *inputContainer) {
78
79 const HWIdentifier id=digit->hardwareID();
80 if (!(*cabling)->isOnlineConnected(id)) continue;
81
82 ATH_MSG_VERBOSE("Working on channel " << m_onlineId->channel_name(id));
83
84 const std::vector<short>& samples=digit->samples();
85 const size_t nSamples=samples.size();
86 const int gain=digit->gain();
87 const float p=peds->pedestal(id,gain);
88
89 //The following autos will resolve either into vectors or vector-proxies
90 const auto& ofca=ofcs->OFC_a(id,gain);
91 const auto& adc2mev=adc2MeVs->ADC2MEV(id,gain);
92
93 //Sanity check on input conditions data:
95 ATH_MSG_ERROR("No valid pedestal for channel " << m_onlineId->channel_name(id) << " gain " << gain);
96 return StatusCode::FAILURE;
97 }
98
99 if(ATH_UNLIKELY(adc2mev.size()<2)) {
100 ATH_MSG_ERROR("No valid ADC2MeV for channel " << m_onlineId->channel_name(id) << " gain " << gain);
101 return StatusCode::FAILURE;
102 }
103
104 // Subtract pedestal
105 std::vector<float> samp_no_ped(nSamples,0.0);
106 for (size_t i=0;i<nSamples;++i) {
107 samp_no_ped[i]=samples[i]-p;
108 }
109
110 //Apply OFCs to get amplitude
111 // Evaluate sums in double-precision to get consistent results
112 // across platforms.
113 double A=0;
114 bool passBCIDmax=false;
115 //const size_t len=std::min(ofca.size(),samples.size());
116 size_t nOFC=ofca.size();
117 if (ATH_UNLIKELY(nSamples<nOFC+2)) {
118 ATH_MSG_ERROR("Not enough ADC samples for channel " << m_onlineId->channel_name(id) << " gain " << gain
119 << ". Found " << nSamples << ", expect at least " << nOFC+2 <<".");
120 }
121 //Calculate Amplitude for BC
122 for (size_t i=0;i<nOFC;++i) {
123 A+=static_cast<double>(samp_no_ped[i+1])*ofca[i];
124 }
125 //Calcuclate Amplitude for preceeding BC
126 double Abefore=0.;
127 for (size_t i=0;i<nOFC;++i) {
128 Abefore+=static_cast<double>(samp_no_ped[i])*ofca[i];
129 }
130 //Calculate Amplitude for trailing BC
131 double Aafter=0.;
132 for (size_t i=0;i<nOFC;++i) {
133 Aafter+=static_cast<double>(samp_no_ped[i+2])*ofca[i];
134 }
135 //set passBCIDmax if Amplitude at assume BC is larger than for the BC before and after
136 if ( (A>Abefore) && (A>Aafter) ) passBCIDmax=true;
137
138
139 //Apply Ramp
140 const float E=adc2mev[0]+A*adc2mev[1];
141
142 uint16_t iquaShort=0;
143 float tau=0;
144
145 const float E1=m_absECutFortQ.value() ? std::fabs(E) : E;
146
147 if (E1 > m_eCutFortQ) {
148 ATH_MSG_VERBOSE("Channel " << m_onlineId->channel_name(id) << " gain " << gain << " above threshold for tQ computation");
149
150 //Get time by applying OFC-b coefficients:
151 const auto& ofcb=ofcs->OFC_b(id,gain);
152 double At=0;
153 for (size_t i=0;i<nOFC;++i) {
154 At+=static_cast<double>(samp_no_ped[i+1])*ofcb[i];
155 }
156 //Divide A*t/A to get time
157 tau=(std::fabs(A)>0.1) ? At/A : 0.0;
158 const auto& fullShape=shapes->Shape(id,gain);
159
160 //Get Q-factor
161 size_t firstSample=m_firstSample;
162 // fixing HEC to move +1 in case of 4 samples and firstSample 0 (copied from old LArRawChannelBuilder)
163 if (fullShape.size()>nSamples && nSamples==4 && m_firstSample==0) {
164 if (m_onlineId->isHECchannel(id)) {
165 firstSample=1;
166 }
167 }
168
169 if (ATH_UNLIKELY(fullShape.size()<nOFC+firstSample)) {
170 ATH_MSG_DEBUG("No valid shape for channel " << m_onlineId->channel_name(id)
171 << " gain " << gain);
172 ATH_MSG_DEBUG("Got size " << fullShape.size() << ", expected at least " << nSamples+firstSample);
173 //return StatusCode::FAILURE;
174 nOFC=fullShape.size()-firstSample;
175 }
176
177 const float* shape=&*fullShape.begin()+firstSample;
178
179 double q=0;
180 bool useShapeDer=m_useShapeDer;
181 if (useShapeDer) {
182 const auto& fullshapeDer=shapes->ShapeDer(id,gain);
183 if (ATH_UNLIKELY(fullshapeDer.size()<nOFC)) {
184 ATH_MSG_DEBUG("No valid shape derivative for channel " << m_onlineId->channel_name(id)
185 << " gain " << gain << ". Will not use shape derivative.");
186 useShapeDer=false;
187 }
188 if (useShapeDer) {
189 const float* shapeDer=&*fullshapeDer.begin()+firstSample;
190 for (size_t i=0;i<nOFC;++i) {
191 q += std::pow((A*(shape[i]-tau*shapeDer[i])-(samp_no_ped[i+1])),2);
192 }
193 }//end if useShapeDer
194 }
195 if (!useShapeDer){
196 //Q-factor w/o shape derivative
197 for (size_t i=0;i<nOFC;++i) {
198 q += std::pow((A*shape[i]-(samp_no_ped[i+1])),2);
199 }
200 }
201
202 int iqua = static_cast<int>(q);
203 if (iqua > 0xFFFF) iqua=0xFFFF;
204 iquaShort = static_cast<uint16_t>(iqua & 0xFFFF);
205
206 tau-=ofcs->timeOffset(id,gain);
207 }//end if above cut
208
209 CaloCell* ss = dataPool.nextElementPtr();
210 Identifier offId = cabling->cnvToIdentifier(id);
211
212 const CaloDetDescrElement* dde = caloMgr->get_element (offId);
213 ss->setCaloDDE(dde);
214 ss->setEnergy(E);
215 ss->setTime(tau);
216 ss->setGain((CaloGain::CaloGain)0);
217 float et = ss->et()*1e-3; // et in GeV
218 // for super-cells provenance and time are slightly different
219 uint16_t prov = LArProv::QTPRESENT;//0x2000;
220 if(et>10e3 && tau>-8 && tau<16) prov |= LArProv::SCTIMEPASS; //0x200;
221 else if(et<=10e3 && std::fabs(tau)<8) prov |= LArProv::SCTIMEPASS; //0x200;
222 if ( passBCIDmax ) prov |= LArProv::SCPASSBCIDMAX; //0x40;
223 // set some provenance to indicate bad channel
224 if(badchannel) {
225 LArBadChannel bc = badchannel->offlineStatus(offId);
227 prov |= 0x80;
228 }
229 }
230
231 ss->setProvenance(prov);
232
233 ss->setQuality(iquaShort);
234 outputContainerCellPtr->push_back(ss);
235
236 }//end loop over input digits
237
239 ATH_CHECK(outputContainer.record(std::move(outputContainerCellPtr) ) );
240
241 return StatusCode::SUCCESS;
242}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_DEBUG(x)
#define ATH_UNLIKELY(x)
Definition of CaloDetDescrManager.
LArBadXCont< LArBadChannel > LArBadChannelCont
static Double_t ss
const ServiceHandle< StoreGateSvc > & detStore() const
Data object for each calorimeter readout cell.
Definition CaloCell.h:57
This class groups all DetDescr information related to a CaloCell.
const CaloDetDescrElement * get_element(const Identifier &cellId) const
get element by its identifier
a typed memory pool that saves time spent allocation small object.
Definition DataPool.h:63
void reserve(unsigned int size)
Set the desired capacity.
pointer nextElementPtr()
obtain the next available element in pool by pointer pool is resized if its limit has been reached On...
unsigned int allocated()
return size already allocated OK
virtual OFCRef_t OFC_b(const HWIdentifier &id, int gain, int tbin=0) const =0
virtual OFCRef_t OFC_a(const HWIdentifier &id, int gain, int tbin=0) const =0
access to OFCs by online ID, gain, and tbin (!=0 for testbeam)
virtual float timeOffset(const HWIdentifier &CellID, int gain) const =0
virtual float pedestal(const HWIdentifier &id, int gain) const =0
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
const LArVectorProxy ADC2MEV(const HWIdentifier &id, int gain) const
Definition LArADC2MeV.h:32
bool statusBad(PosType pb) const
Returns true if corresponding status bit its set.
bool good() const
Returns true if no problems at all (all bits at zero)
LArBC_t offlineStatus(const Identifier id) const
Query the status of a particular channel by offline ID This is the main client access method.
Liquid Argon digit base class.
Definition LArDigit.h:25
SG::ReadCondHandleKey< ILArPedestal > m_pedestalKey
SG::ReadCondHandleKey< ILArShape > m_shapeKey
Gaudi::Property< float > m_eCutFortQ
Gaudi::Property< int > m_firstSample
SG::ReadCondHandleKey< CaloSuperCellDetDescrManager > m_caloSuperCellMgrKey
Gaudi::Property< bool > m_absECutFortQ
const LArOnline_SuperCellID * m_onlineId
SG::WriteHandleKey< CaloCellContainer > m_cellKey
SG::ReadCondHandleKey< LArBadChannelCont > m_bcContKey
Bad Channel masking for Super-Cells.
StatusCode execute(const EventContext &ctx) const override
SG::ReadHandleKey< LArDigitContainer > m_digitKey
SG::ReadCondHandleKey< LArADC2MeV > m_adc2MeVKey
SG::ReadCondHandleKey< ILArOFC > m_ofcKey
SG::ReadCondHandleKey< LArOnOffIdMapping > m_cablingKey
Gaudi::Property< bool > m_useShapeDer
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
@ VIEW_ELEMENTS
this data object is a view, it does not own its elmts
hold the test vectors and ease the comparison
Extra patterns decribing particle interation process.