ATLAS Offline Software
Loading...
Searching...
No Matches
LArOFCCondAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3 */
4
5#include <cmath>
6
7//FIXME
8//are these threadsafe?
10#include "CaloDetDescr/CaloDetDescrElement.h"
12
13#include <Eigen/Dense>
14
15#include "LArOFCCondAlg.h"
16
18
21
22LArOFCCondAlg::LArOFCCondAlg(const std::string &name,
23 ISvcLocator *pSvcLocator)
24 : ::AthCondAlgorithm(name, pSvcLocator),
25 m_LArOnOffIdMappingObjKey("LArOnOffIdMap"),
26 m_LArShapeObjKey("LArShapeSym"),
27 m_LArNoiseObjKey("LArNoiseSym"),
28 m_LArPedestalObjKey("LArPedestal"),
29 m_LArAutoCorrTotalObjKey("LArAutoCorrTotal"),
30 m_LArOFCObjKey("LArOFC"),
31 m_Nminbias(0), m_isMC(true),
32 m_isSuperCell(false), m_firstSample(0),
33 m_useHighestGainAutoCorr(false), m_Dump(false) {
34 declareProperty("LArOnOffIdMappingObjKey", m_LArOnOffIdMappingObjKey,
35 "Key to read LArOnOffIdMapping object");
36 declareProperty("LArShapeObjKey", m_LArShapeObjKey,
37 "Key to read LArShape object");
38 declareProperty("LArNoiseObjKey", m_LArNoiseObjKey,
39 "Key to read LArNoise object");
40 declareProperty("LArPedestalObjKey", m_LArPedestalObjKey,
41 "Key to read LArPedestal object");
42 declareProperty("LArAutoCorrTotalObjKey", m_LArAutoCorrTotalObjKey,
43 "Key to read LArAutoCorrTotal object");
44 declareProperty("LArOFCObjKey", m_LArOFCObjKey,
45 "Key to write LArOFC object");
46 declareProperty("Nminbias", m_Nminbias);
47 declareProperty("isMC", m_isMC);
48 declareProperty("isSuperCell", m_isSuperCell);
50 "firstSample", m_firstSample,
51 "First sample to use for in-time event on the full pulse shape");
52 declareProperty("useHighestGainAutoCorr",m_useHighestGainAutoCorr);
53 declareProperty("DumpOFCCondAlg",m_Dump);
54 declareProperty("NGains",m_nGains);
55 }
56
58
60 ATH_MSG_DEBUG("initialize " << name());
61
62 // ReadCondHandle initialization
63 ATH_CHECK(m_LArShapeObjKey.initialize());
64
67
68 //WriteHandle initialization
69 ATH_CHECK(m_LArOFCObjKey.initialize());
70
73
74 if (m_isSuperCell && m_nGains!=1) {
75 ATH_MSG_ERROR("Inconsistent configuration: m_isSuperCell set but nGains != 1");
76 return StatusCode::FAILURE;
77 }
78
79 return StatusCode::SUCCESS;
80}
81
82StatusCode LArOFCCondAlg::execute(const EventContext& ctx) const {
83
84 // WriteHandle setup
86 // So the following should not be called usually?!
87 if (writeHandle.isValid()) {
89 "CondHandle "
90 << writeHandle.fullKey() << " is already valid.");
91 return StatusCode::SUCCESS;
92 }
93
94 // Identifier helper
95 // Copied from LArADC2MeVCondAlg.cxx
96 const LArOnlineID_Base *larOnlineID = nullptr;
97 if (m_isSuperCell) {
98 const LArOnline_SuperCellID *scidhelper;
99 ATH_CHECK(detStore()->retrieve(scidhelper, "LArOnline_SuperCellID"));
100 larOnlineID = scidhelper; // cast to base-class
101 } else { // regular cells
102 const LArOnlineID *idhelper;
103 ATH_CHECK(detStore()->retrieve(idhelper, "LArOnlineID"));
104 larOnlineID = idhelper; // cast to base-class
105 }
106
107 // Mapping helper
108 const LArOnOffIdMapping *larOnOffIdMapping = nullptr;
109 SG::ReadCondHandle<LArOnOffIdMapping> larOnOffIdMappingHdl{
111 };
112 larOnOffIdMapping = *larOnOffIdMappingHdl;
113 if (larOnOffIdMapping == nullptr) {
114 ATH_MSG_ERROR("Failed to retrieve LArOnOffIdMapping object");
115 return StatusCode::FAILURE;
116 }
117 writeHandle.addDependency(larOnOffIdMappingHdl);
118
119 // Get pointers to inputs
120 // Retrieve validity ranges and determine their intersection
122 // FIXME: should check if handle is properly created and/or check if handle is
123 // properly retrieved
124 // operator star of a ReadCondHandle returns a const pointer to type T
125 const ILArShape *larShape{ *ShapeHdl };
126 if (larShape == nullptr) {
127 ATH_MSG_ERROR("Failed to retrieve LArShape object");
128 return StatusCode::FAILURE;
129 }
130 writeHandle.addDependency(ShapeHdl);
131
133 const LArAutoCorrTotal *larAutoCorrTotal = nullptr;
134 larAutoCorrTotal= *AutoCorrTotalHdl;
135 if (larAutoCorrTotal == nullptr) {
136 ATH_MSG_ERROR("Failed to retrieve LArADC2MeV object");
137 return StatusCode::FAILURE;
138 }
139 writeHandle.addDependency(AutoCorrTotalHdl);
140
141 // Consider the determinstic objects
142 const ILArNoise *larNoise = nullptr;
143 const ILArPedestal *larPedestal = nullptr;
144
145 if (m_isMC) {
147 larNoise = *NoiseHdl;
148 if (larNoise == nullptr) {
149 ATH_MSG_ERROR("Failed to retrieve object LArNoise");
150 return StatusCode::FAILURE;
151 }
152 writeHandle.addDependency(NoiseHdl);
153 } else {
155 larPedestal = *PedestalHdl;
156 if (larPedestal == nullptr) {
157 ATH_MSG_ERROR("Failed to retrieve object LArPedestal");
158 return StatusCode::FAILURE;
159 }
160 writeHandle.addDependency(PedestalHdl);
161 }
162
163 ATH_MSG_INFO("IOV found from intersection for LArOFCCondObj object: "
164 << writeHandle.getRange());
165
166 // make output object
167 // dimensions: number of gains x number of channel IDs x elements of
168 // OFC
169 std::unique_ptr<LArOFC> larOFC =
170 std::make_unique<LArOFC>(larOnlineID, larOnOffIdMapping, m_nGains);
171
172 std::vector<float> OFCa_tmp, OFCb_tmp;
173
174 for (const HWIdentifier chid : larOnlineID->channel_range()) {
175 const IdentifierHash hid = larOnlineID->channel_Hash(chid);
176
177 //if (!(larOnOffIdMapping->isOnlineConnected(chid))) continue;
178 if (larOnOffIdMapping->isOnlineConnected(chid)) {
179 for (size_t igain = 0; igain < m_nGains; igain++) {
180
181
182 //:::::::::::::::::::::::::::::::
183 //retrieve the data
184 //:::::::::::::::::::::::::::::::
185 ILArShape::ShapeRef_t Shape = larShape->Shape(chid,igain);
186 unsigned int nsamples_shape = Shape.size();
187 ILArShape::ShapeRef_t ShapeDer = larShape->ShapeDer(chid,igain);
188 //:::::::::::::::::::::::::::::::
189
190 // get Noise autocorrelation for gain
191 int igain_autocorr = 0;
192 // to use only Autocorr fro highest gain in optimization: HEC/FCAL=> medium gain EM=>high gain
194 &&(larOnlineID->isHECchannel(chid) || larOnlineID->isFCALchannel(chid)) ) igain_autocorr=1;
195
196 const std::vector<double> AutoCorr =
197 larAutoCorrTotal->autoCorrTotal(chid,igain_autocorr,m_Nminbias);
198 //unsigned int nsamples_AC_OFC=AutoCorr.size()+1;
199 unsigned int nsamples_AC_OFC = (1+((int)(sqrt(1+8*AutoCorr.size()))))/2;
200
201 const std::vector<double>& rmsSampl =
202 larAutoCorrTotal->samplRMS(chid,igain_autocorr,m_Nminbias);
203 unsigned int nsamples2 = rmsSampl.size();
204 if (nsamples2 != nsamples_AC_OFC) {
205 ATH_MSG_WARNING( " bad size for rmsSampl " );
206 //return (m_OFCtmp); // return empty vector
207 }
208 //:::::::::::::::::::::::::::::::
209 //unsigned int iBeginOfNSamples=findTheNSamples(Shape,
210 // nsamples_AC_OFC,
211 // nsamples_shape);
212 unsigned int firstSample = m_firstSample;
213 if(larOnlineID->isHECchannel(chid) && m_firstSample == 0 && nsamples_AC_OFC==4){
214 firstSample=1;
215 }
216 unsigned int iBeginOfNSamples = firstSample;
217 if(nsamples_AC_OFC + iBeginOfNSamples > nsamples_shape)
218 iBeginOfNSamples=0;
219 //:::::::::::::::::::::::::::::::
220
221 if(m_isMC) {
222 }
223 else
224 {
225 float RMSpedestal = larPedestal->pedestalRMS(chid,igain);
226 if(RMSpedestal>= (1.0+LArElecCalib::ERRORCODE))
227 ;
228 else
229 {
230 ATH_MSG_WARNING(" PedestalRMS vector empty for "
231 <<chid<<" at gain "<<igain );
232 }
233 }
234 //:::::::::::::::::::::::::::::::
235 //protection against missing data
236 //:::::::::::::::::::::::::::::::
237 if(Shape.size()==0 || ShapeDer.size()==0 || AutoCorr.empty())
238 {
239 ATH_MSG_WARNING("Some data are missing -> OFC will be empty for "
240 <<chid<<" at gain "<<igain );
241 //return (m_OFCtmp);
242 //returns an empty vector
243 }
244 if (Shape.size()!=ShapeDer.size()) {
245 ATH_MSG_ERROR("Got invalid shape object: Size=" << Shape.size() << ", DerSize=" << ShapeDer.size());
246 return StatusCode::SUCCESS;
247 }
248 //:::::::::::::::::::::::::::::::
249 unsigned int l,c,i;
250 //:::::::::::::::::::::::::::::::
251 //calculations
252 //:::::::::::::::::::::::::::::::
253 // fill and inverrt AC matrix
254 //HepMatrix AC(nsamples_AC_OFC,nsamples_AC_OFC),
255 //ACinv(nsamples_AC_OFC,nsamples_AC_OFC);
256 Eigen::MatrixXf AC = Eigen::MatrixXf::Zero(nsamples_AC_OFC,nsamples_AC_OFC);
257 Eigen::MatrixXf ACinv = Eigen::MatrixXf::Zero(nsamples_AC_OFC,nsamples_AC_OFC);
258 for(l=0;l<nsamples_AC_OFC;++l) { // l=line c=column
259 for(c=0;c<nsamples_AC_OFC;++c) {
260 if (l==c) {
261 AC(l,c)=1.;
262 }
263 else {
264 int i1=std::min(l,c);
265 int i2=std::max(l,c);
266 int index = i1*nsamples_AC_OFC - i1*(i1+1)/2 -(i1+1) + i2;
267 AC(l,c)=AutoCorr[index];
268 }
269 AC(l,c) = AC(l,c)*rmsSampl[l]*rmsSampl[c];
270 }
271 }
272 ACinv=AC.inverse();
273 //:::::::::::::::::::::::::::::::
274
275
276 float ACinv_PS[32];//ACinv_PS
277 float ACinv_PSD[32]; //ACinv_PSD
278 //Q1 Q2 Q3 DELTA
279 float Q1=0.;
280 float Q2=0.;
281 float Q3=0.;
282
283 for(l=0;l<nsamples_AC_OFC;++l)
284 {
285 ACinv_PS[l]=0.; ACinv_PSD[l]=0.;
286 for(c=0;c<nsamples_AC_OFC;++c){
287 ACinv_PS[l]+=ACinv(l,c)*Shape[c+iBeginOfNSamples];
288 ACinv_PSD[l]+=ACinv(l,c)*ShapeDer[c+iBeginOfNSamples];
289 }
290 Q1+=Shape[l+iBeginOfNSamples]*ACinv_PS[l];
291 Q2+=ShapeDer[l+iBeginOfNSamples]*ACinv_PSD[l];
292 Q3+=ShapeDer[l+iBeginOfNSamples]*ACinv_PS[l];
293 }
294 float DELTA=Q1*Q2-Q3*Q3;
295 //:::::::::::::::::::::::::::::::
296 //OFCa
297 OFCa_tmp.resize(nsamples_AC_OFC);
298 for(i=0;i<nsamples_AC_OFC;++i)
299 OFCa_tmp[i]=(ACinv_PS[i]*Q2-ACinv_PSD[i]*Q3)/DELTA;
300 //OFCb
301 OFCb_tmp.resize(nsamples_AC_OFC);
302 for(i=0;i<nsamples_AC_OFC;++i)
303 OFCb_tmp[i]=(ACinv_PS[i]*Q3-ACinv_PSD[i]*Q1)/DELTA;
304
305 //for debugging only
306 if(m_Dump)
307 {
308 std::cout<<larOnlineID
309 ->show_to_string(larOnOffIdMapping->cnvToIdentifier(chid))
310 <<" gain="<<igain<<" Nminbias="<<m_Nminbias<<std::endl;
311 std::cout<<"Shape: ";
312 for(c=0;c<nsamples_shape;++c)
313 std::cout<<Shape[c]<<" ";
314 std::cout<<std::endl;
315 std::cout<<"ShapeDer: ";
316 for(c=0;c<nsamples_shape;++c)
317 std::cout<<ShapeDer[c]<<" ";
318 std::cout<<std::endl;
319 for(c=0;c<nsamples_AC_OFC;++c)
320 std::cout<<Shape[c+iBeginOfNSamples]<<" ";
321 std::cout<<" <- "<<iBeginOfNSamples<<std::endl;
322 for(i=0;i<nsamples_AC_OFC;++i) std::cout<<ACinv_PS[i]<<" ";
323 std::cout<<std::endl;
324 for(i=0;i<nsamples_AC_OFC;++i) std::cout<<ACinv_PSD[i]<<" ";
325 std::cout<<std::endl;
326 std::cout<<" Q1="<<Q1<<" Q2="<<Q2<<" Q3="<<Q3
327 <<" DELTA="<<DELTA<<std::endl;
328 std::cout << " OFCa: ";
329 for(i=0;i<nsamples_AC_OFC;++i)
330 std::cout<<(ACinv_PS[i]*Q2-ACinv_PSD[i]*Q3)/DELTA<<" ";
331 std::cout<<std::endl;
332 }
333 bool stat = larOFC->setOFC(hid, igain, std::make_pair(OFCa_tmp, OFCb_tmp));
334 if (!stat) {
335 msg(MSG::ERROR) << "LArOFC::setOFC fails for gain " << igain << ", hash " << hid << endmsg;
336 }
337 } // end loop over gains
338 } else { // end loop over connected channels -- now, set empty for disc. chnanels
339 for (unsigned igain=0;igain<m_nGains;++igain) {
340 std::vector<float> empty;
341 bool stat = larOFC->setOFC(hid,igain, std::make_pair(empty, empty));
342 if (!stat) {
343 msg(MSG::ERROR) << "LArOFC::setOFC fails for gain " << igain << ", hash " << hid << endmsg;
344 }
345 } // end loop over gains of disconnected channels
346 } // end loop over disconnected channels
347
348 } // end loop over all channels
349
350
351 ATH_CHECK(writeHandle.record(std::move(larOFC)));
352 ATH_MSG_INFO("Wrote LArOFC obj to CondStore");
353 return StatusCode::SUCCESS;
354}
355
357 unsigned int nsamples_AC_OFC,
358 unsigned int nsamples_shape) const
359{
360 unsigned int i_ShapeMax=0;
361 double ShapeMax=0;
362 for(unsigned int i=0;i<nsamples_shape;++i)
363 {
364 double value=Shape[i];
365 if(value>ShapeMax) { ShapeMax=value; i_ShapeMax=i; }
366 else if(value<0 && i>3) break;//after the peak
367 }
368
369 unsigned int tmp=int(nsamples_AC_OFC/2.);
370 if(tmp>i_ShapeMax) return 0;
371 else return i_ShapeMax-tmp;
372}
#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_WARNING(x)
#define ATH_MSG_DEBUG(x)
Definition of CaloDetDescrManager.
static const double DELTA
static const Attributes_t empty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
const ServiceHandle< StoreGateSvc > & detStore() const
Base class for conditions algorithms.
std::string show_to_string(Identifier id, const IdContext *context=0, char sep='.') const
or provide the printout in string form
virtual float pedestalRMS(const HWIdentifier &id, int gain) const =0
access to RMS of Pedestal index by Identifier, and gain setting
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
This is a "hash" representation of an Identifier.
const std::vector< double > autoCorrTotal(const IdentifierHash &hid, int gain, float Nminbias) const
const std::vector< double > samplRMS(const IdentifierHash &hid, int gain, float Nminbias) const
unsigned int m_firstSample
virtual StatusCode execute(const EventContext &ctx) const override
virtual StatusCode initialize() override
SG::WriteCondHandleKey< LArOFC > m_LArOFCObjKey
unsigned int findTheNSamples(ILArShape::ShapeRef_t Shape, unsigned int nsamples_AC_OFC, unsigned int nsamples_shape) const
SG::ReadCondHandleKey< LArOnOffIdMapping > m_LArOnOffIdMappingObjKey
bool m_useHighestGainAutoCorr
SG::ReadCondHandleKey< ILArShape > m_LArShapeObjKey
SG::ReadCondHandleKey< LArAutoCorrTotal > m_LArAutoCorrTotalObjKey
LArOFCCondAlg(const std::string &name, ISvcLocator *pSvcLocator)
SG::ReadCondHandleKey< ILArNoise > m_LArNoiseObjKey
virtual ~LArOFCCondAlg() override
SG::ReadCondHandleKey< ILArPedestal > m_LArPedestalObjKey
Identifier cnvToIdentifier(const HWIdentifier &sid) const
create an Identifier from a HWIdentifier (inline)
bool isOnlineConnected(const HWIdentifier &sid) const
Test whether a HWIdentifier is connected of not (inline) .
Helper for the Liquid Argon Calorimeter cell identifiers.
id_range channel_range() const
IdentifierHash channel_Hash(HWIdentifier channelId) const
Create channel_hash from channel_Id.
bool isFCALchannel(const HWIdentifier id) const
virtual bool isHECchannel(const HWIdentifier id) const =0
void addDependency(const EventIDRange &range)
const EventIDRange & getRange() const
StatusCode record(const EventIDRange &range, T *t)
record handle, with explicit range DEPRECATED
const DataObjID & fullKey() const
Definition index.py:1