ATLAS Offline Software
Loading...
Searching...
No Matches
LArWFParamTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
12
13#include <cmath>
14#ifndef __APPLE__
15#include <values.h>
16#else
17#include <float.h>
18#endif
19#include <cassert>
20
21#ifndef LAR_MAX_DOUBLE
22#ifndef __APPLE__
23#define LAR_MAX_DOUBLE MAXDOUBLE
24#else
25#define LAR_MAX_DOUBLE __DBL_MAX__
26#endif
27#endif
28
29const double LArWFParamTool::m_DEFAULT = -1;
30const double LArWFParamTool::m_TINY=2.22045e-16;
31const double LArWFParamTool::m_SQRT_EPSILON=1.49012e-08;
32const double LArWFParamTool::m_EPSILON=2.22045e-16;
33
34//double fminbr(double a, double b, double (*f)(double), double tol);
35
36LArWFParamTool::LArWFParamTool ( const std::string& type, const std::string& name,const IInterface* parent )
37 : AthAlgTool(type,name,parent),
38 m_NBaseline(0),
39 m_ShiftToStart(false),
40 m_SubtractBaseline(false),
42{
43
44 // Declare additional interface
45 declareInterface<LArWFParamTool>(this);
46
47 declareProperty("NBaseline", m_NBaseline);
48 declareProperty("ShiftToStart", m_ShiftToStart);
49 declareProperty("SubtractBaseline", m_SubtractBaseline);
50 declareProperty("isSC", m_isSC = false);
51
52 m_DeltaTtail.resize(3);
53 int default_deltattail[3] = { 100, 50, 0 } ;
54 for ( unsigned i=0; i<3; ++i )
55 m_DeltaTtail[i] = default_deltattail[i] ;
56 declareProperty("DeltaTtail", m_DeltaTtail);
57
58 m_TtailMin.resize(4);
59 m_TtailMax.resize(4);
60 int default_ttailmin[4] = { 0, 0, 0, 0 };
61 int default_ttailmax[4] = { 0, 0, 0, 0 };
62 for ( unsigned i=0; i<4; ++i ) {
63 m_TtailMin[i] = default_ttailmin[i];
64 m_TtailMax[i] = default_ttailmax[i];
65 }
66 declareProperty("TtailMin", m_TtailMin);
67 declareProperty("TtailMax", m_TtailMax);
68
69 // flags to force cos resp scan:
70 m_cosRespScan.resize(4) ;
71 bool defaults[4] = { false , true , false , true } ;
72 for ( unsigned i=0 ; i<4 ; ++i )
73 m_cosRespScan[i] = defaults[i] ;
74 declareProperty("CosRespScan", m_cosRespScan ) ;
75
76
77 // omega0 intervals and granularities:
78 //float default_omegamin[4] = { 0.01 , 0.47 , 0.10 , 0.30 } ;
79 //float default_omegamax[4] = { 1.00 , 0.48 , 0.30 , 0.60 } ;
80 //unsigned default_npoints[4] = { 100 , 50 , 100 , 100 } ;
81 float default_omegamin[4] = { 0.01 , 0.10 , 0.10 , 0.10 };
82 float default_omegamax[4] = { 1.00 , 0.33 , 0.20 , 0.33 };
83 unsigned default_npoints[4] = { 100 , 100 , 100 , 100 };
84 m_omegamin.resize(4) ;
85 m_omegamax.resize(4) ;
86 m_npoints.resize(4) ;
87 for ( unsigned i=0 ; i<4 ; ++i ) {
88 m_omegamin[i] = default_omegamin[i] ;
89 m_omegamax[i] = default_omegamax[i] ;
90 m_npoints[i] = default_npoints[i] ;
91 }
92 declareProperty("Omega0Min", m_omegamin);
93 declareProperty("Omega0Max", m_omegamax);
94 declareProperty("NpointScan", m_npoints );
95 declareProperty("UseOmegaScanHelper", m_UseOmegaScanHelper );
96
97 // flags to save residual oscillation
98 m_storeResOscill.resize(4,false) ;
99 declareProperty("StoreResOscill", m_storeResOscill) ;
100
101 declareProperty("TShaper", m_Tshaper=15.) ;
102}
103
104// destructor
106= default;
107
108//const InterfaceID& LArWFParamTool::interfaceID( )
109//{ return IID_ILArWFParamTool; }
110
111
113{
114 std::string layerName[4] = { "PS" , "Strips" , "Middle" , "Back" } ;
115
116 ATH_MSG_INFO( "TShaper set to " << m_Tshaper << " ns" ) ;
117
118 ATH_MSG_INFO( "Step response (Fstep) -> Ttail = Tmin + " << m_DeltaTtail[0] << " steps" ) ;
119
121 ATH_MSG_INFO( "Cosine response (Omega0) -> Ttail = Tmin + " << m_DeltaTtail[1] << " steps" ) ;
122 else
123 ATH_MSG_INFO( "Cosine response (Omega0) -> Will use OmegaScanHelper() to dynamically select settings" );
124
125 ATH_MSG_INFO( "Residual oscillations (Taur) -> Ttail = Tmin + " << m_DeltaTtail[2] << " steps" ) ;
126
127 for ( unsigned layer=0 ; layer<4 ; ++layer ) {
128 ATH_MSG_INFO( "options for Layer " << layer << " (" << layerName[layer] << ")" ) ;
129
130 ATH_MSG_INFO( " perform cos resp scan: " );
131 if ( m_cosRespScan[layer] && !m_UseOmegaScanHelper )
132 ATH_MSG_INFO( "YES (" << m_npoints[layer] << " points)" ) ;
133 if ( !m_cosRespScan[layer] && !m_UseOmegaScanHelper )
134 ATH_MSG_INFO( "NO" ) ;
136 ATH_MSG_INFO( "Will use OmegaScanHelper() to dynamically select settings" ) ;
137
139 ATH_MSG_INFO( " search interval: [ " << m_omegamin[layer] << " ; " << m_omegamax[layer] << " ]" ) ;
140 if ( m_omegamin[layer] >= m_omegamax[layer] ) {
141 ATH_MSG_ERROR( "Omega0Min >= Omega0Max in layer " << layer << " -- exit!" ) ;
142 return StatusCode::FAILURE ;
143 }
144 }
145
146 ATH_MSG_INFO( " store residual oscillation wave:" );
147 if ( m_storeResOscill[layer] ) {
148 ATH_MSG_INFO( "YES" ) ;
149 } else {
150 ATH_MSG_INFO( "NO" ) ;
151 }
152
153 }
154
155
156 StatusCode sc;
157 if ( m_isSC ) {
158 const LArOnline_SuperCellID* ll;
159 ATH_CHECK(detStore()->retrieve(ll, "LArOnline_SuperCellID"));
160 m_onlineHelper = static_cast<const LArOnlineID_Base*>(ll);
161 ATH_MSG_DEBUG("Found the LArOnlineID helper");
162
163 } else { // m_isSC
164 const LArOnlineID* ll;
165 ATH_CHECK(detStore()->retrieve(ll, "LArOnlineID") );
166 m_onlineHelper = static_cast<const LArOnlineID_Base*>(ll);
167 ATH_MSG_DEBUG(" Found the LArOnlineID helper. ");
168
169 }
170
171
172 const CaloIdManager *caloIdMgr=nullptr;
173 ATH_CHECK( detStore()->retrieve(caloIdMgr));
174 if(!caloIdMgr){
175 ATH_MSG_ERROR( "Could not access CaloIdManager" );
176 return StatusCode::FAILURE;
177 }
178 if ( m_isSC ) {
179 m_emId=caloIdMgr->getEM_SuperCell_ID();
180 } else {
181 m_emId=caloIdMgr->getEM_ID();
182 }
183 if (!m_emId) {
184 ATH_MSG_ERROR( "Could not access lar EM ID helper" );
185 return StatusCode::FAILURE;
186 }
187
188
189 return StatusCode::SUCCESS;
190}
191
192
193StatusCode LArWFParamTool::getLArWaveParams(const LArCaliWave& larCaliWave,
194 const HWIdentifier chid,
195 const CaloGain::CaloGain gain,
196 LArWFParams& wfParams,
197 const LArOnOffIdMapping *cabling,
198 std::optional<LArCaliWave>& omegaScanWave,
199 std::optional<LArCaliWave>& resOscill0,
200 std::optional<LArCaliWave>& resOscill1) const
201{
202
203
204 wfParams.setTshaper(m_Tshaper);
205 LArCaliWave gCali=larCaliWave; //down-cast to LArWave + deep copy (we'll modify the wave)
206
207 // find m_Tstart, m_Tpeak, m_Tcross, m_Tmin, m_Amplitude
208 WaveTiming_t waveTiming=timeExtr(gCali);
209
210 // find m_Tcal
211 if ( wfParams.tcal() == DoExtract ) {
212 const double Tcal = expTail(gCali,waveTiming) ;
213 if ( Tcal < 0 ) {
214 ATH_MSG_WARNING( "Could not extract Tcal for " << m_onlineHelper->channel_name(chid)
215 << " gain=" << (int)gain ) ;
216 wfParams.setTcal(FailExtract);
217 return StatusCode::FAILURE;
218 }
219 else {
220 wfParams.setTcal(Tcal);
221 }
222 ATH_MSG_VERBOSE( "set Tcal = " << wfParams.tcal()) ;
223 }
224
225 // find m_Fstep
226 if ( wfParams.fstep() == DoExtract ) {
227 StatusCode sc = GetFstep(gCali,wfParams,waveTiming);
228 if ( sc.isFailure() ) {
229 ATH_MSG_WARNING( "Could not extract Fstep for " << m_onlineHelper->channel_name(chid)
230 << " gain=" << (int)gain );
231 wfParams.setFstep(FailExtract);
232 return sc ;
233 }
234 } else {
235 ATH_MSG_VERBOSE( "set Fstep = " <<wfParams.fstep() );
236 }
237
238 // find m_Omega0 using RTM
239 if ( wfParams.omega0() == DoExtract ) {
240 StatusCode sc = RTM_Omega0(gCali,chid,wfParams,waveTiming,cabling,omegaScanWave);
241 if ( sc.isFailure() ) {
242 ATH_MSG_WARNING( "Could not extract Omega0 for " << m_onlineHelper->channel_name(chid)
243 << " gain=" << (int)gain );
244 wfParams.setOmega0(FailExtract) ;
245 return sc ;
246 }
247 } else {
248 ATH_MSG_VERBOSE( "set Omega0 = " << wfParams.omega0());
249 }
250
251
252 const Identifier id = cabling->cnvToIdentifier(chid);
253 const unsigned layer=m_emId->sampling(id);
254 if ( m_storeResOscill[ layer ] && resOscill0) {
255 LArWave injres0 = injRespRes(gCali,wfParams.omega0(),0);
256 *resOscill0 = LArCaliWave(injres0.getWave(),gCali.getDt(),gCali.getDAC(), 0x1,LArWave::unknown);
257 }
258
259 // find m_Taur using RTM
260 if ( wfParams.taur() == DoExtract ) {
261 StatusCode sc = RTM_Taur(gCali, wfParams,waveTiming ) ;
262 if ( sc.isFailure() ) {
263 ATH_MSG_WARNING( "Could not extract Taur for ChID=" << chid.get_compact()
264 << " gain=" << (int)gain ) ;
265 wfParams.setTaur(FailExtract);
266 return sc ;
267 }
268 ATH_MSG_VERBOSE( "set Taur = " << wfParams.taur() );
269 }
270
271 wfParams.setFlag( 0 ) ; // this should contain the method used to find parameters and the gain
272
273 if ( m_storeResOscill[ layer ] && resOscill1 && wfParams.omega0() != 0) {
274 LArWave injres1 = injRespRes(gCali,wfParams.omega0(),wfParams.taur());
275 *resOscill1 = LArCaliWave(injres1.getWave(),gCali.getDt(),gCali.getDAC(), 0x1, LArWave::unknown);
276 }
277
278 return( StatusCode::SUCCESS );
279}
280
281
282
284{
285 WaveTiming_t wt{}; //return object
286
287 wt.Tstart = m_wHelper.getStart(gCali);
288
289 const unsigned NBaseline= m_NBaseline==0 ? wt.Tstart : m_NBaseline ;
290
291 const double baseline = m_wHelper.getBaseline(gCali,NBaseline);
292
293 if ( m_ShiftToStart ) // move the wave to the start
294 gCali = m_wHelper.translate(gCali, -wt.Tstart, baseline);
295
296 if ( m_SubtractBaseline ) // remove the baseline
297 gCali = gCali + (-baseline);
298
299 wt.Tpeak = m_wHelper.getMax(gCali);
300
301 wt.Amplitude = gCali.getSample(wt.Tpeak);
302
303 wt.Tmin = m_wHelper.getMin(gCali);
304
305 wt.Tcross = m_wHelper.getZeroCross(gCali);
306
307 return wt;
308}
309
310
311double LArWFParamTool::expTail(const LArWave& gCali, const WaveTiming_t& wt) const
312{
313 unsigned int t1;
314 unsigned int t2;
315 if ( m_TtailMin[0]!=0 && m_TtailMax[0]!=0 && m_TtailMin[0]<m_TtailMax[0] ) {
316 t1 = m_TtailMin[0];
317 t2 = m_TtailMax[0];
318 } else {
319 const unsigned nAfterMin = 150;
320 const unsigned nBeforeEnd = 125;
321 t1 = wt.Tmin + nAfterMin;
322 t2 = gCali.getSize() - nBeforeEnd ; // last points rejected because sometimes are crazy!
323 }
324 ATH_MSG_VERBOSE( "exp-fitting between " << t1 << " and " << t2 ) ;
325
326 double A, rho ;
327 std::vector<double> fitPars = m_wHelper.expfit(gCali,t1,t2,rho) ; // fit to B*exp(A*t) function
328 if (fitPars.size() == 2 ) {
329 A = fitPars[1];
330 //B = fitPars[0];
331 } else {
332 return -1;
333 }
334
335 const double Tcal = -1./A ;
336 if ( Tcal < 0 ) {
337 ATH_MSG_WARNING( "Exponential fit yielded negative Tcal " << Tcal );
338 }
339 ATH_MSG_VERBOSE( "*** Exponential fit\t--> m_Tcal = " << Tcal ) ;
340
341 return Tcal;
342}
343
344StatusCode LArWFParamTool::GetFstep(const LArWave& gCali, LArWFParams& wfParams, const WaveTiming_t& wt) const
345{
346 // step response
347 const unsigned Ttail = wt.Tmin + m_DeltaTtail[0];
348 //m_Fstep = 0.; // starting point for iterations
349 const double fstep1=0.0;
350 const double Tcal=wfParams.tcal();
351 wfParams.setFstep(fstepMin(gCali,fstep1,Tcal,Ttail) );
352 //ATH_MSG_VERBOSE( "*** Step response\t--> m_Fstep = " << m_Fstep ) ;
353 return StatusCode::SUCCESS ;
354}
355
356double LArWFParamTool::fstepMin (const LArWave& gCali, double fstep, const double Tc, const unsigned Ttail) const {
357 int niter = 0;
358 //double dfstep;
359 while (1) {
360 niter++ ;
361 const double dfstep = dFstep(gCali,fstep,Tc,Ttail) ;
362 fstep += dfstep ;
363 if ( niter > 50 || fstep < 0. ) {
364 fstep = 0.;
365 break;
366 }
367 if ( fabs( dfstep ) <= m_TINY ) break;
368 }
369 return fstep;
370}
371
372double LArWFParamTool::dFstep (const LArWave& gCali, const double fstep, const double Tc, const unsigned Ttail) const {
373 LArWave stepResp1 = stepResp(gCali, fstep, Tc) ;
374 LArWave dstepRespDfstep1 = dstepRespDfstep(gCali,fstep,Tc) ;
375 //LArWaveHelper wHelper;
376 double a,b;
377 if ( m_TtailMin[1]!=0 && m_TtailMax[1]!=0 && m_TtailMin[1]<m_TtailMax[1] ) {
378 b = m_wHelper.getSumRegion( stepResp1 * dstepRespDfstep1,m_TtailMin[1],m_TtailMax[1]);
379 a = m_wHelper.getSumSquareRegion( dstepRespDfstep1,m_TtailMin[1],m_TtailMax[1]);
380 } else {
381 b = m_wHelper.getSumTail( stepResp1 * dstepRespDfstep1,Ttail);
382 a = m_wHelper.getSumSquareTail( dstepRespDfstep1,Ttail);
383 }
384 if (a == 0) return 0;
385 return -b/a ;
386}
387
388LArWave LArWFParamTool::stepResp (const LArWave& gCali, const double fstep, const double Tc) {
389 //return m_gCali + m_gCali % stepCorr() ;
390 LArWave result = gCali % stepCorr(gCali, fstep, Tc);
391 result+=gCali;
392 return result;
393}
394
395LArWave LArWFParamTool::stepCorr(const LArWave& gCali, const double& fstep, const double& Tc) {
396 const unsigned N = gCali.getSize() ;
397 const double dt = gCali.getDt() ;
398
399 LArWave w(N,dt);
400 const double A=(1.-fstep)/Tc;
401 for ( unsigned i=0 ; i<N ; i++ ) {
402 w.setSample(i,A*exp(-fstep*i*dt/Tc));
403 }
404 return w ;
405}
406
407LArWave LArWFParamTool::dstepRespDfstep (const LArWave& gCali, const double& fstep, const double& Tc) const {
408 return gCali % dstepCorrDfstep(gCali,fstep,Tc);
409}
410
411double LArWFParamTool::dstepCorrDfstep (const double t, const double& fstep, const double& Tc ) {
412 return (-1./Tc)*(1.+((1.-fstep)/Tc)*t)*exp(-fstep*t/Tc);
413}
414
415LArWave LArWFParamTool::dstepCorrDfstep(const LArWave& gCali, const double& fstep, const double& Tcal ) {
416 const unsigned N = gCali.getSize() ;
417 const double dt = gCali.getDt() ;
418 LArWave w(N,dt);
419 for ( unsigned i=0 ; i<N ; i++ ) w.setSample(i,dstepCorrDfstep(i*dt,fstep,Tcal)) ;
420 return w ;
421}
422
423StatusCode LArWFParamTool::RTM_Omega0(const LArWave& gCali, const HWIdentifier chid, LArWFParams& wfParams, const WaveTiming_t& wt, const LArOnOffIdMapping *cabling, std::optional<LArCaliWave>& omegaScanWave) const
424{
425 /* begin of the COSINE RESPONSE analysis */
426
427 const Identifier id = cabling->cnvToIdentifier(chid);
428 // Define the (raw) minimum research interval (if the Layer card is not set,
429 // uses the wider interval, and default value for the first minimum scan)
430
431 omegaScanParams_t OSParams{};
432
433 // defaults (e.g. to be used in case cosRespScan=true)
434 OSParams.cosRespScan = true ;
435 OSParams.omegamin = 0.01 ;
436 OSParams.omegamax = 1. ;
437 OSParams.Npoint = 100 ;
438 OSParams.DeltaOmega = 0.01 ; // GHz
439 OSParams.range.min=m_TtailMin[2];
440 OSParams.range.max=m_TtailMax[2];
441
442 if ( !m_UseOmegaScanHelper) {
443 const unsigned layer=m_emId->sampling(id);
444 OSParams.cosRespScan = m_cosRespScan[ layer ] ;
445 OSParams.omegamin = m_omegamin[ layer ] ;
446 OSParams.omegamax = m_omegamax[ layer ] ;
447 OSParams.Npoint = m_npoints[ layer ] ;
448 OSParams.DeltaOmega = 0.02 ;
449 //DeltaOmega = 0.001 ;
450 } else {
451 OSParams=OmegaScanHelper(id,wt);
452 }
453
454 waveRange_t range=OSParams.range;
455//if (m_TtailMin[2]==0 || m_TtailMax[2]==0 || m_TtailMin[2]>=m_TtailMax[2]) {
456 if (range.min==0 || range.max==0 || range.min>=range.max) {
457 range.min=wt.Tmin + m_DeltaTtail[1];
458 range.max=gCali.getSize();
459 }
460
461 if ( OSParams.cosRespScan ){
462 // makes a raw scan of the cosresp chi2 logarithm
463 const double dOmega = (OSParams.omegamax-OSParams.omegamin)/OSParams.Npoint;
464 const unsigned vectSize = (unsigned) ceil ( OSParams.omegamax/dOmega );
465 const unsigned indexmin = (unsigned) floor( OSParams.omegamin/dOmega );
466 if (omegaScanWave) omegaScanWave->setSize(vectSize);
467 double chi2min = LAR_MAX_DOUBLE, omega0raw = LAR_MAX_DOUBLE;
468 for (int i=0;i<OSParams.Npoint;i++) {
469 const double omega = OSParams.omegamin+dOmega*i ;
470 const double chi2 = logChi2CosRespShaper(omega, gCali, wfParams, range);
471 if (omegaScanWave) omegaScanWave->setSample(i+indexmin,chi2);
472 if ( chi2 < chi2min ) {
473 chi2min = chi2;
474 omega0raw = omega;
475 }
476 }
477
478 OSParams.omegamin = omega0raw - OSParams.DeltaOmega ;
479 OSParams.omegamax = omega0raw + OSParams.DeltaOmega ;
480 }
481
482 if ( OSParams.omegamin == OSParams.omegamax ) { // skip cosine response calculation
483 wfParams.setOmega0(0.); // this will force no injection point correction in LArPhysWavePredictor
484 ATH_MSG_VERBOSE( "*** Cosine response skipped\t--> m_Omega0 = " << wfParams.omega0() ) ;
485 } else { // numerical (Brent) log(chi2) minimization
486 wfParams.setOmega0(omega0MinNum ( OSParams.omegamin, OSParams.omegamax, m_EPSILON, gCali, wfParams, range) );
487 ATH_MSG_VERBOSE( "*** Cosine response\t--> m_Omega0 = " <<wfParams.omega0() ) ;
488 }
489
490 /* end of the COSINE RESPONSE analysis */
491 return StatusCode::SUCCESS ;
492}
493
494
496
497 omegaScanParams_t ret{};
498
499 // this is a skeleton of the final function: use at your own risk! M.D. & C.G.
500 // EMEC part modified by L. March - 7 April 2011
501
502 const unsigned layer=m_emId->sampling(id);
503
504 ret.range.min = m_TtailMin[2];
505 ret.range.max = m_TtailMax[2];
506 ret.cosRespScan = m_cosRespScan[ (unsigned)layer ] ;
507 ret.omegamin = m_omegamin[ (unsigned)layer ] ;
508 ret.omegamax = m_omegamax[ (unsigned)layer ] ;
509 ret.Npoint = m_npoints[ (unsigned)layer ] ;
510 ret.DeltaOmega = 0.02 ;
511 //DeltaOmega = 0.001 ;
512
513 //if ( m_BarrelEC==0 ) { // Barrel
514 if (m_emId->is_em_barrel(id)) {
515
516 if ( layer==0 ) { // PS
517 ret.range.min = wt.Tstart;
518 ret.range.max = wt.Tcross;
519 ret.cosRespScan = m_cosRespScan[ (unsigned)layer ];
520 ret.omegamin = 0.240;
521 ret.omegamax = 0.330;
522 ret.Npoint = 900;
523 }
524
525 if ( layer==1 ) { // Strips
526 ret.range.min = wt.Tstart;
527 ret.range.max = wt.Tcross;
528 ret.cosRespScan = true;
529 // Strips interval 1
530 //ret.omegamin = 0.150;
531 //ret.omegamax = 0.220;
532 //ret.Npoint = 700;
533 // Strips interval 2
534 ret.omegamin = 0.220;
535 ret.omegamax = 0.310;
536 ret.Npoint = 900;
537 // Strips interval 3
538 //omegamin = 0.310;
539 //omegamax = 0.390;
540 //Npoint = 1400;
541 }
542
543 if ( layer==2 ) { // Middle
544 ret.range.min = wt.Tstart;
545 ret.range.max = wt.Tmin + m_DeltaTtail[1];
546 ret.cosRespScan = false;
547 ret.omegamin = 0.060;
548 ret.omegamax = 0.215;
549 //Npoint = 315;
550 }
551
552 if ( layer==3 ) { // Back
553 ret.range.min = wt.Tstart;
554 ret.range.max = wt.Tcross;
555 ret.cosRespScan = false;
556 ret.omegamin = 0.100;
557 ret.omegamax = 0.700;
558 ret.Npoint = 120;
559 }
560
561 }
562 else {
563 //if ( m_BarrelEC==1 ) { // EndCap
564
565 // use pulse peak to perform cosine response tranformation minimization
566 //ret.range.min = m_Tstart;
567 //ret.range.max = m_Tcross;
568 ret.range.min = 0.;
569 ret.range.max = 0.;
570
571 ret.DeltaOmega = 0.001 ;
572
573 //(*m_log) << MSG::WARNING << " m_Tstart= " << m_Tstart << " m_Tcross=" << m_Tcross ) ;
574
575 const bool IsEMECInnerWheel = m_emId->is_em_endcap_inner(id);//m_onlineHelper->isEMECinHECchannel(m_chID);
576 const int eta=m_emId->eta(id);
577 if ( IsEMECInnerWheel ) { // EMEC Inner Wheel
578
579 if ( layer==1 ) {
580 //omegamin = 0.10 ;
581 //omegamax = 0.20 ;
582 ret.omegamin = 0.12 ;
583 if(eta>=0 && eta<=3)
584 {
585 ret.omegamin = 0.12 ;
586 //omegamax = 0.165 ;
587 ret.omegamax = 0.16 ;
588 ret.Npoint=100;
589 }
590 if(eta>=4 && eta<=6)
591 {
592 ret.omegamin = 0.14 ;
593 ret.omegamax = 0.18 ;
594 ret.Npoint=100;
595 }
596 } else
597 if ( layer == 2 ) { // don't extract Omega0
598 /*
599 cosRespScan = false;
600 omegamin = 0.;
601 omegamax = 0.;
602 Npoint = 0;
603 DeltaOmega = 0.;
604 */
605 ret.cosRespScan = true;
606 ret.omegamin = 0.12;
607 ret.omegamax = 0.35;
608 ret.Npoint = 100;
609 } else { // don't extract Omega0
610 ret.cosRespScan = false;
611 ret.omegamin = 0.;
612 ret.omegamax = 0.;
613 ret.Npoint = 0;
614 ret.DeltaOmega = 0.;
615 }
616
617 } else { // EMEC Outer Whell
618
619 if ( layer==1 ) { // don't extract Omega0
620 ret.cosRespScan = false;
621 ret.omegamin = 0.;
622 ret.omegamax = 0.;
623 ret.Npoint = 0;
624 ret.DeltaOmega = 0.;
625 } else
626 if ( layer == 2 ) {
627 ret.cosRespScan = true;
628 ret.Npoint =100;
629 ret.omegamin=0.1;
630 if(eta==0) {
631 ret.omegamax = 0.140 ;
632 }
633 if(eta==1) {
634 ret.omegamax = 0.135 ;
635 }
636 if(eta==2) {
637 ret.omegamax = 0.15 ;
638 }
639 if(eta==3) {
640 ret.omegamin = 0.10;
641 ret.omegamax = 0.16;
642 }
643 if(eta>=4 && eta<11 ) {
644 ret.omegamin = 0.12 ;
645 ret.omegamax = 0.20 ;
646 }
647 if(eta==11) {
648 ret.omegamin = 0.12 ;
649 ret.omegamax = 0.22 ;
650 }
651 if(eta>=12 && eta<28) {
652 ret.omegamin = 0.12 ;
653 ret.omegamax = 0.24 ;
654 }
655 if(eta>=28 && eta<39) {
656 ret.omegamin = 0.12 ;
657 ret.omegamax = 0.245 ;
658 }
659 if(eta>=39 && eta<43) {
660 //ret.omegamin = 0.12 ;
661 ret.omegamin = 0.24 ;
662 ret.omegamax = 0.32 ;
663 }
664 } else { // don't extract Omega0
665 ret.cosRespScan = false;
666 ret.omegamin = 0.;
667 ret.omegamax = 0.;
668 ret.Npoint = 0;
669 ret.DeltaOmega = 0.;
670 }
671
672 } // end of EMEC Outer Wheel
673
674 } // end of EMEC
675
676 return ret;
677}
678
679
680StatusCode LArWFParamTool::RTM_Taur(const LArWave& gCali, LArWFParams& wf, const WaveTiming_t& wt) const
681{
682 /* begin of the INJECTION POINT CORRECTION RESIDUAL OSCILLATION analysis */
683
684 // m_Taur minimum search interval...
685 double taurmin = 0.; // ns
686 //double taurmax = 4.; // ns
687 double taurmax = 100.; // ns
688
689 if ( wf.omega0()==0) {
690 wf.setTaur(0);
691 ATH_MSG_VERBOSE( "*** Injection point skipped\t--> m_Taur = " << wf.taur() ) ;
692 } else {
693 // numerical (Brent) log(chi2) minimization
694 waveRange_t range{};
695 if ( m_TtailMin[3]!=0 && m_TtailMax[3]!=0 && m_TtailMin[3]<m_TtailMax[3]) {
696 range.min=m_TtailMin[3];
697 range.max=m_TtailMax[3];
698 }
699 else {
700 range.min= wt.Tmin + m_DeltaTtail[2];
701 range.max=gCali.getSize();
702 }
703
704 wf.setTaur(taurMinNum ( taurmin, taurmax, m_EPSILON, gCali, wf, range));
705 ATH_MSG_VERBOSE( "*** Injection point\t--> m_Taur = " << wf.taur()) ;
706 }
707
708 /* end of the INJECTION POINT CORRECTION RESIDUAL OSCILLATION analysis */
709
710 return StatusCode::SUCCESS ;
711}
712
713double LArWFParamTool::logChi2CosRespShaper (const double omega, const LArWave& gCali, const LArWFParams& wfParams, const waveRange_t& range) const {
714 return log(m_wHelper.getSumSquareRegion(cosRespShaper(gCali,wfParams.fstep(),wfParams.tcal(),omega,wfParams.tshaper()),range.min,range.max)) ;
715}
716
717LArWave LArWFParamTool::cosRespShaper (const LArWave& gCali, const double& fstep, const double& tcal, const double& w, const double& tsh ) const {
718 return cosResp(gCali,fstep,tcal, w) * ( pow((1.+ w*w*tsh*tsh),1.5)/(w*tsh));
719}
720
721/******************************************************************
722 * Cosine response
723 *****************************************************************/
724LArWave LArWFParamTool::cosResp (const LArWave& gCali, const double& fstep, const double& tcal, const double& omega) {
725
726 LArWave result=gCali % cosCorr(gCali.getSize(),gCali.getDt(),fstep, tcal, omega);
727 result+=gCali;
728 return result;
729}
730
731/* =================================================================
732 * Function: Cosine response correction function
733 * ============================================================== */
734LArWave LArWFParamTool::cosCorr(const unsigned N, const double dt, const double fstep, const double Tc, const double omega) {
735 LArWave w(N,dt);
736 const double C1=(fstep*fstep-fstep*fstep*fstep)/Tc;
737 const double C2=(fstep+omega*omega*Tc*Tc);
738 const double C3=(fstep-1.)*omega*Tc;
739 const double C4=( fstep*fstep+omega*omega*Tc*Tc );
740 for ( unsigned i=0 ; i<N ; i++ ) {
741 const double t=i*dt;
742 //const double p=((fstep*fstep-fstep*fstep*fstep)/Tc*exp(-fstep*t/Tc) - omega*((fstep+omega*omega*Tc*Tc)*sin(omega*t)+(fstep-1.)*omega*Tc*cos(omega*t)) ) / ( fstep*fstep+omega*omega*Tc*Tc ) ;
743 const double p=(C1*exp(-fstep*t/Tc) - omega*(C2*sin(omega*t) + C3*cos(omega*t))) / C4 ;
744 w.setSample(i,p);
745 }
746 return w ;
747}
748
749
750/* ================================================================
751 * log of the chi2 built on the tail of the injection point correction
752 * residual oscillation, to be used in numerical minimisation.
753 * ============================================================== */
754double LArWFParamTool::logChi2InjRespRes (const double taur, const LArWave& gCali, const LArWFParams& wf, const waveRange_t& range) const {
755 return m_wHelper.getSumSquareRegion(injRespRes(gCali,wf.omega0(),taur), range.min, range.max);
756}
757
758LArWave LArWFParamTool::injRespRes (const LArWave& w, const double omega0, const double taur) {
759 return w - ( w % injCorr(w.getSize(),w.getDt(),omega0,taur) );
760}
761
762LArWave LArWFParamTool::injCorr(const unsigned N, const double dt,const double omega0, const double taur) {
763
764 LArWave w(N,dt);
765
766 const double tau0 = 1./omega0;
767 const double Delta = taur*taur - 4*tau0*tau0;
768 if ( Delta > 0 ) {
769 const double sqrtDelta = sqrt(Delta) ;
770 const double taup = 0.5*( taur + sqrtDelta ) ;
771 const double taum = 0.5*( taur - sqrtDelta ) ;
772 for ( unsigned i=0 ; i<N ; i++ ) {
773 const double t=i*dt;
774 w.setSample(i, (exp(-t/taup) - exp(-t/taum) ) / (taup - taum));
775 }
776 //return ( exp(-t/taup) - exp(-t/taum) ) / ( taup - taum ) ;
777 } else if ( Delta < 0 ) {
778 const double T = sqrt(-Delta) ;
779 const double A = 2 * taur / ( (taur*taur) - Delta ) ;
780 const double B = 2 * T / ( (taur*taur) - Delta );
781 for ( unsigned i=0 ; i<N ; i++ ) {
782 const double t=i*dt;
783 w.setSample(i, 2 * exp(-A*t) * sin(B*t) / T);
784 }
785 //return 2 * exp(-A*t) * sin(B*t) / T ;
786 } else { //Delta==0
787 const double tau = 0.5 * taur ;
788 // return exp(-t/tau) * t / pow(tau,2) ;
789 for ( unsigned i=0 ; i<N ; i++ ) {
790 const double t=i*dt;
791 w.setSample(i,exp(-t/tau) * t / (tau*tau)) ;
792 }
793 //return exp(-t/tau) * t / (tau*tau) ;
794 } //end else
795 return w;
796}
797
798double LArWFParamTool::omega0MinNum (double omegaMin, double omegaMax, const double tol, const LArWave& gCali, const LArWFParams& wf, const waveRange_t& range) const {
799 return fminbr ( omegaMin, omegaMax, tol, &LArWFParamTool::logChi2CosRespShaper, gCali, wf, range);
800}
801
802
803
804
805
806
807double LArWFParamTool::taurMinNum (const double taurmin, const double taurmax, const double tol, const LArWave& gCali, const LArWFParams& wf, const waveRange_t& range ) const {
808 return fminbr ( taurmin, taurmax, tol, &LArWFParamTool::logChi2InjRespRes, gCali, wf, range );
809}
810
811/*
812 ************************************************************************
813 * C math library
814 * function FMINBR - one-dimensional search for a function minimum
815 * over the given range
816 *
817 * Input
818 * double fminbr(a,b,f,tol)
819 * double a; Minimum will be seeked for over
820 * double b; a range [a,b], a being < b.
821 * double (*f)(double x); Name of the function whose minimum
822 * will be seeked for
823 * double tol; Acceptable tolerance for the minimum
824 * location. It have to be positive
825 * (e.g. may be specified as m_EPSILON)
826 *
827 * Output
828 * Fminbr returns an estimate for the minimum location with accuracy
829 * 3*m_SQRT_EPSILON*abs(x) + tol.
830 * The function always obtains a local minimum which coincides with
831 * the global one only if a function under investigation being
832 * unimodular.
833 * If a function being examined possesses no local minimum within
834 * the given range, Fminbr returns 'a' (if f(a) < f(b)), otherwise
835 * it returns the right range boundary value b.
836 *
837 * Algorithm
838 * G.Forsythe, M.Malcolm, C.Moler, Computer methods for mathematical
839 * computations. M., Mir, 1980, p.202 of the Russian edition
840 *
841 * The function makes use of the "gold section" procedure combined with
842 * the parabolic interpolation.
843 * At every step program operates three abscissae - x,v, and w.
844 * x - the last and the best approximation to the minimum location,
845 * i.e. f(x) <= f(a) or/and f(x) <= f(b)
846 * (if the function f has a local minimum in (a,b), then the both
847 * conditions are fulfiled after one or two steps).
848 * v,w are previous approximations to the minimum location. They may
849 * coincide with a, b, or x (although the algorithm tries to make all
850 * u, v, and w distinct). Points x, v, and w are used to construct
851 * interpolating parabola whose minimum will be treated as a new
852 * approximation to the minimum location if the former falls within
853 * [a,b] and reduces the range enveloping minimum more efficient than
854 * the gold section procedure.
855 * When f(x) has a second derivative positive at the minimum location
856 * (not coinciding with a or b) the procedure converges superlinearly
857 * at a rate order about 1.324
858 *
859 ************************************************************************
860 */
861
862//#include "fminbr.h"
863//#include "small_nums.h"
864
865double LArWFParamTool::fminbr(double a, double b, const double tol, double (LArWFParamTool::*f)(double, const LArWave&, const LArWFParams&, const waveRange_t&) const,
866 const LArWave& gCali, const LArWFParams& wf, const waveRange_t& waverange) const
867/* fminbr(a,b,f,tol) An estimate to the min location
868 a; Left border | of the range
869 b; Right border | the min is seeked
870 (*f)(double x) Function under investigation
871 tol; Acceptable tolerance */
872
873{
874 double x,v,w; /* Abscissae, descr. see above */
875 double fx; /* f(x) */
876 double fv; /* f(v) */
877 double fw; /* f(w) */
878 const double r = (3.-sqrt(5.0))/2; /* Gold section ratio */
879
880 assert( tol > 0 && b > a );
881
882 v = a + r*(b-a); fv = (this->*f)(v,gCali,wf,waverange); /* First step - always gold section*/
883 x = v; w = v;
884 fx=fv; fw=fv;
885
886 for(;;) /* Main iteration loop */
887 {
888 double range = b-a; /* Range over which the minimum */
889 /* is seeked for */
890 double middle_range = (a+b)/2;
891 double tol_act = /* Actual tolerance */
892 m_SQRT_EPSILON*fabs(x) + tol/3;
893 double new_step; /* Step at this iteration */
894
895 if( fabs(x-middle_range) + range/2 <= 2*tol_act )
896 return x; /* Acceptable approx. is found */
897
898 /* Obtain the gold section step */
899 new_step = r * ( x<middle_range ? b-x : a-x );
900
901
902 /* Decide if the interpolation can be tried */
903 if( fabs(x-w) >= tol_act ) /* If x and w are distinct */
904 { /* interpolatiom may be tried */
905 double p; /* Interpolation step is calcula-*/
906 double q; /* ted as p/q; division operation*/
907 /* is delayed until last moment */
908 double t;
909
910 t = (x-w) * (fx-fv);
911 q = (x-v) * (fx-fw);
912 p = (x-v)*q - (x-w)*t;
913 q = 2*(q-t);
914
915 if( q>(double)0 ) /* q was calculated with the op-*/
916 p = -p; /* posite sign; make q positive */
917 else /* and assign possible minus to */
918 q = -q; /* p */
919
920 if( fabs(p) < fabs(new_step*q) && /* If x+p/q falls in [a,b]*/
921 p > q*(a-x+2*tol_act) && /* not too close to a and */
922 p < q*(b-x-2*tol_act) ) /* b, and isn't too large */
923 new_step = p/q; /* it is accepted */
924 /* If p/q is too large then the */
925 /* gold section procedure can */
926 /* reduce [a,b] range to more */
927 /* extent */
928 }
929
930 if( fabs(new_step) < tol_act ) { /* Adjust the step to be not less*/
931 if( new_step > (double)0 ) /* than tolerance */
932 new_step = tol_act;
933 else
934 new_step = -tol_act;
935 }
936
937 /* Obtain the next approximation to min */
938 { /* and reduce the enveloping range */
939 double t = x + new_step; /* Tentative point for the min */
940 double ft = (this->*f)(t,gCali,wf,waverange);
941 if( ft <= fx )
942 { /* t is a better approximation */
943 if( t < x ) /* Reduce the range so that */
944 b = x; /* t would fall within it */
945 else
946 a = x;
947
948 v = w; w = x; x = t; /* Assign the best approx to x */
949 fv=fw; fw=fx; fx=ft;
950 }
951 else /* x remains the better approx */
952 {
953 if( t < x ) /* Reduce the range enclosing x */
954 a = t;
955 else
956 b = t;
957
958 if( ft <= fw || w==x )
959 {
960 v = w; w = t;
961 fv=fw; fw=ft;
962 }
963 else if( ft<=fv || v==x || v==w )
964 {
965 v = t;
966 fv=ft;
967 }
968 }
969 } /* ----- end-of-block ----- */
970 } /* ===== End of loop ===== */
971}
972
973
974
975
976unsigned LArWFParamTool::checkStatus(const LArCaliWave &larCaliWave) const
977{
978 // this is supposed to be a quick test on cali waves, to flags those
979 // clearly problematic. but cuts must be tuned, so for the time being
980 // don't call this method!
981
982 //MsgStream log(msgSvc(), name());
983
984 unsigned length ;
985 if ( (length=larCaliWave.getSize()) < 750 ) {
986 ATH_MSG_WARNING( "Calibration wave is too short!" ) ;
987 return TooShort ;
988 }
989
990 const unsigned range = 2 ;
991 unsigned nMax = 0 ;
992 double tremble = 0 ;
993 double maxSample = -9.E+10 ;
994 for ( unsigned i=0 ; i<length ; i++ ) {
995 if ( larCaliWave.getError(i) < 0 || larCaliWave.getTrigger(i) < 0 ) {
996 ATH_MSG_WARNING( "Calibration wave probably not completely filled" ) ;
997 return NotFilled ;
998 }
999 if ( larCaliWave.getTrigger(i) < 50 ) {
1000 ATH_MSG_WARNING( "Calibration wave with low statistics" ) ;
1001 return LowStat ;
1002 }
1003 double thisSample = larCaliWave.getTrigger(i) ;
1004 if ( thisSample > maxSample ) maxSample = thisSample ;
1005 if ( i>=range && i<length-range ) {
1006 bool max = true ;
1007 double loc_tremble = 0 ;
1008 for ( unsigned k=i-range ; k<=i+range ; k++ ) {
1009 double delta = thisSample - larCaliWave.getSample(k) ;
1010 loc_tremble += delta*delta;// pow(delta,2) ;
1011 if ( delta < 0 ) max = false ;
1012 }
1013 if ( max ) nMax ++ ;
1014 tremble += loc_tremble / (2*range) ;
1015 }
1016 }
1017 if ( sqrt(tremble/length)/maxSample > 0.1 ) {
1018 ATH_MSG_WARNING( "Calibration wave is noisy " << sqrt(tremble/length)/maxSample ) ;
1019 return Noisy ;
1020 }
1021 if ( nMax > 1 ) {
1022 ATH_MSG_WARNING( "Calibration wave oscillates" ) ;
1023 return Oscillating ;
1024 }
1025
1026 return OK ;
1027}
Scalar eta() const
pseudorapidity method
#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)
double length(const pvec &v)
Helper class for LArEM offline identifiers for supercells.
static Double_t Tc(Double_t t)
static Double_t taup
static Double_t a
static Double_t sc
static Double_t tau0
#define LAR_MAX_DOUBLE
@ baseline
#define x
constexpr int pow(int base, int exp) noexcept
#define max(a, b)
Definition cfImp.cxx:41
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
const ServiceHandle< StoreGateSvc > & detStore() const
This class initializes the Calo (LAr and Tile) offline identifiers.
const LArEM_SuperCell_ID * getEM_SuperCell_ID(void) const
const LArEM_ID * getEM_ID(void) const
value_type get_compact() const
Get the compact id.
int getDAC() const
DAC value.
Helper for the Liquid Argon Calorimeter cell identifiers.
StatusCode getLArWaveParams(const LArCaliWave &larCaliWave, const HWIdentifier chid, const CaloGain::CaloGain gain, LArWFParams &wfParams, const LArOnOffIdMapping *cabling, std::optional< LArCaliWave > &omegaScan, std::optional< LArCaliWave > &resOscill0, std::optional< LArCaliWave > &resOscill1) const
LArWFParamTool(const std::string &type, const std::string &name, const IInterface *parent)
LArWaveHelper m_wHelper
static double dstepCorrDfstep(const double t, const double &fstep, const double &Tc)
double fstepMin(const LArWave &gCali, double fstep, const double Tc, const unsigned Ttail) const
const LArOnlineID_Base * m_onlineHelper
std::vector< bool > m_cosRespScan
double dFstep(const LArWave &gCali, const double fstep, const double Tc, const unsigned Ttail) const
double expTail(const LArWave &gCali, const WaveTiming_t &wt) const
static const double m_EPSILON
double taurMinNum(const double taurmin, const double taurmax, const double tol, const LArWave &gCali, const LArWFParams &wf, const waveRange_t &) const
StatusCode GetFstep(const LArWave &gCali, LArWFParams &wfParams, const WaveTiming_t &wt) const
static LArWave cosResp(const LArWave &gCali, const double &fstep, const double &tcal, const double &omega)
double logChi2CosRespShaper(const double omega, const LArWave &gCali, const LArWFParams &wf, const waveRange_t &range) const
static LArWave stepCorr(const LArWave &gCali, const double &fstep, const double &Tc)
omegaScanParams_t OmegaScanHelper(const Identifier id, const WaveTiming_t &wt) const
unsigned checkStatus(const LArCaliWave &larCaliWave) const
StatusCode RTM_Taur(const LArWave &gCali, LArWFParams &wfParams, const WaveTiming_t &wt) const
static LArWave stepResp(const LArWave &gCali, const double fstep, const double Tc)
double logChi2InjRespRes(const double taur, const LArWave &gCali, const LArWFParams &wf, const waveRange_t &range) const
std::vector< double > m_omegamin
std::vector< int > m_TtailMax
static LArWave cosCorr(const unsigned N, const double dt, const double fstep, const double tcal, const double omega)
unsigned int m_NBaseline
static const double m_DEFAULT
static LArWave injCorr(const unsigned N, const double dt, const double omega0, const double taur)
const LArEM_Base_ID * m_emId
std::vector< bool > m_storeResOscill
double fminbr(double a, double b, const double tol, double(LArWFParamTool::*f)(double, const LArWave &, const LArWFParams &, const waveRange_t &) const, const LArWave &gCali, const LArWFParams &wf, const waveRange_t &range) const
static const double m_SQRT_EPSILON
LArWave cosRespShaper(const LArWave &gCali, const double &fstep, const double &tcal, const double &w, const double &tsh) const
std::vector< int > m_TtailMin
std::vector< unsigned > m_npoints
double omega0MinNum(double omegaMin, double omegaMax, const double tol, const LArWave &gCali, const LArWFParams &wf, const waveRange_t &) const
virtual StatusCode initialize()
virtual ~LArWFParamTool()
StatusCode RTM_Omega0(const LArWave &gCali, const HWIdentifier chid, LArWFParams &wfParams, const WaveTiming_t &wt, const LArOnOffIdMapping *cabling, std::optional< LArCaliWave > &omegaScan) const
std::vector< double > m_omegamax
std::vector< int > m_DeltaTtail
LArWave dstepRespDfstep(const LArWave &gCali, const double &fstep, const double &Tc) const
static const double m_TINY
static LArWave injRespRes(const LArWave &w, const double omega0, const double taur)
WaveTiming_t timeExtr(LArWave &gCali) const
void setTaur(double taur)
double omega0() const
void setFstep(double fstep)
double tshaper() const
void setTcal(double tcal)
void setOmega0(double omega0)
double fstep() const
void setFlag(unsigned flag)
void setTshaper(double tsh)
double tcal() const
double taur() const
double getError(unsigned i) const
error per time bin
int getTrigger(unsigned i) const
trigger per time bin
size_t getSize() const
number of time samples
Definition LArWave.h:62
@ unknown
Definition LArWave.h:137
const double & getSample(const unsigned int i) const
Amplitude per time bin.
Definition LArWave.h:53
const std::vector< double > & getWave() const
Wave parameters.
Definition LArWave.h:167
const double & getDt() const
delta time
Definition LArWave.h:50
double chi2(TH1 *h0, TH1 *h1)
int r
Definition globals.cxx:22
hold the test vectors and ease the comparison