ATLAS Offline Software
LArBarrelCalculator.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 // The Cell Identifier for the EM Barrel readout cells
6 
7 // Adapted from code written by Gaston Parrour
8 // Adaptation by Sylvain Negroni
9 // 17-11-2003: G.Unal cleanup
10 // 18-03-2003: G.Unal major revision to use new current maps
11 
12 // #define DEBUGSTEP
13 // #define DEBUGSTEP2
14 
15 #include "LArBarrelCalculator.h"
16 #include "AccMap.h"
17 #include "MapEta.h"
18 
21 
22 #include "G4ThreeVector.hh"
23 #include "G4StepPoint.hh"
24 #include "G4Step.hh"
25 #include "G4ios.hh"
26 #include "G4AffineTransform.hh"
27 #include "G4NavigationHistory.hh"
28 #include "G4VTouchable.hh"
29 #include "G4TouchableHistory.hh"
30 
31 #include <cmath>
32 #include <iostream>
33 
34 #include "GaudiKernel/ISvcLocator.h"
35 #include "GaudiKernel/Bootstrap.h"
36 #include "StoreGate/StoreGateSvc.h"
37 #include "AthenaKernel/Units.h"
38 
39 #include "LArHV/LArHVManager.h"
40 #include "LArHV/EMBHVManager.h"
41 #include "LArHV/EMBHVModule.h"
42 #include "LArHV/EMBHVElectrode.h"
43 
44 namespace Units = Athena::Units;
45 
46 // ================================================================================
47 LArBarrelCalculator::LArBarrelCalculator(const std::string& name, ISvcLocator* pSvcLocator)
48  : LArCalculatorSvcImp(name, pSvcLocator)
49 {
50 }
51 
53 {
54  ATH_MSG_DEBUG("LArBarrelCalculator: Beginning initialization ");
55  if (m_BirksLaw) {
56  const double Birks_LAr_density = 1.396;
57  ATH_MSG_INFO("Use Birks_LAr_density="<<Birks_LAr_density<<", Birksk="<<(double)m_Birksk);
58  m_birksLaw = new LArG4BirksLaw(Birks_LAr_density,m_Birksk);
59  }
60 
61  // Access source of detector parameters.
63 
64  // Get the out-of-time cut from the detector parameters routine.
65  m_OOTcut = parameters->GetValue("LArExpHallOutOfTimeCut"); //FIXME should be done via configurables
66  ATH_MSG_DEBUG("**** OutOfTime cut " << m_OOTcut);
67 
68  // Main Barrel parameters
69  // All the UNITS are implicitly the GEANT4 ONES e.g. mm, rad, etc ...
70  m_etaMaxBarrel = parameters->GetValue("LArEMBMaxEtaAcceptance");
71  m_zMinBarrel = parameters->GetValue("LArEMBfiducialMothZmin");
72  m_zMaxBarrel = parameters->GetValue("LArEMBfiducialMothZmax");
73  m_NCellMax = (int) (parameters->GetValue("LArEMBnoOFPhysPhiCell"));
74  m_rMinAccordion = parameters->GetValue("LArEMBRadiusInnerAccordion");
75  m_rMaxAccordion = parameters->GetValue("LArEMBFiducialRmax");
76 
77  // absorbers and electrodes thickness
78  m_ThickAbs = 0.5*( parameters->GetValue("LArEMBThickAbsGlue")
79  +parameters->GetValue("LArEMBThickAbsIron")
80  +parameters->GetValue("LArEMBThickAbsLead"));
81 
82  G4double check = 0.5*( parameters->GetValue("LArEMBThinAbsGlue")
83  +parameters->GetValue("LArEMBThinAbsIron")
84  +parameters->GetValue("LArEMBThinAbsLead"));
85 
86  if (fabs(check-m_ThickAbs)>0.001)
87  {
88  ATH_MSG_WARNING("Thin and Thick Abs have difference thickness!");
89  }
90 
91  m_ThickEle= 0.5*( parameters->GetValue("LArEMBThickElecCopper")
92  +parameters->GetValue("LArEMBThickElecKapton"));
93 
94  // === GU 11/06/2003 total number of cells in phi
95  // to distinguish 1 module (testbeam case) from full Atlas
96  m_NCellTot = (int) (parameters->GetValue("LArEMBnoOFPhysPhiCell"));
97  if (m_NCellTot != 1024)
98  {
99  m_NCellMax=1024;
100  m_testbeam=true;
101  }
102  // ===
103  // access geometry computation class
104  ATH_CHECK(m_geometry.retrieve());
105 
106  // access current maps if required
107  if (m_IflCur)
108  {
109  ATH_MSG_DEBUG(" LArBarrelCalculator: start reading of current maps");
111  m_etamap1 = std::make_unique<MapEta>(1);
112  m_etamap2 = std::make_unique<MapEta>(2);
113  if (m_IflMapTrans) m_etamap3 = std::make_unique<MapEta>(3);
114  ATH_MSG_DEBUG(" LArBarrelCalculator: end of reading current maps");
115  }
116  // Initialize HV values
117  this->InitHV();
118 
119  ATH_MSG_DEBUG(" LArBarrelCalculator: s_NCellMax " << m_NCellMax);
120  ATH_MSG_DEBUG(" LArBarrelCalculator: s_NCellTot " << m_NCellTot);
121  ATH_MSG_DEBUG(" LArBarrelCalculator: s_rMinAccordion " << m_rMinAccordion);
122  ATH_MSG_DEBUG(" LArBarrelCalculator: s_rMaxAccordion " << m_rMaxAccordion);
123  ATH_MSG_DEBUG(" LArBarrelCalculator: s_zMinBarrel " << m_zMinBarrel);
124  ATH_MSG_DEBUG(" LArBarrelCalculator: s_zMaxBarrel " << m_zMaxBarrel);
125  ATH_MSG_DEBUG(" LArBarrelCalculator: s_etaMaxBarrel " << m_etaMaxBarrel);
126  ATH_MSG_DEBUG(" LArBarrelCalculator: s_ThickAbs " << m_ThickAbs);
127  ATH_MSG_DEBUG(" LArBarrelCalculator: s_ThickEle " << m_ThickEle);
128  if(m_IflCur) ATH_MSG_DEBUG(" LArBarrelCalculator: Deposited Energy dE/dX Corrected ==> CURRENT Option ON");
129  else ATH_MSG_DEBUG(" LArBarrelCalculator: Crude Deposited Energy dE/dX NO CURRENT option");
130  if (m_IflCur && m_IflMapTrans) ATH_MSG_DEBUG(" LArBarrelCalculator: Compute effect of E field around eta=0.8 ");
131  else ATH_MSG_DEBUG(" LArBarrelCalculator: Ignore effect of E field around eta=0.8 ");
132  if(m_BirksLaw)
133  {
134  ATH_MSG_DEBUG(" LArBarrelCalculator: Birks' law ON ");
135  ATH_MSG_DEBUG(" LArBarrelCalculator: parameter k " << m_birksLaw->k());
136  }
137  else
138  {
139  ATH_MSG_DEBUG(" LArBarrelCalculator: Birks' law OFF");
140  }
141 
142  return StatusCode::SUCCESS;
143 }
144 
145 // ============================================================================
147 {
148  if (m_BirksLaw) delete m_birksLaw;
149  return StatusCode::SUCCESS;
150 }
151 
152 // =============================================================================
153 G4bool LArBarrelCalculator::Process(const G4Step* step, std::vector<LArHitData>& hdata) const
154 {
155 
156  hdata.clear();
157 
158  LArG4Identifier identifier2;
159  LArG4Identifier identifier_xt1;
160  LArG4Identifier identifier_xt2;
161 
162  // check the Step content is non trivial
163  G4double thisStepEnergyDeposit = step->GetTotalEnergyDeposit() * step->GetTrack()->GetWeight();
164  G4double thisStepLength = step->GetStepLength() / Units::mm;
165 
166 #ifdef DEBUGSTEP
167  ATH_MSG_DEBUG("****** LArBarrelCalculator: Step energy,length "
168  << thisStepEnergyDeposit << " " << thisStepLength);
169 #endif
170 
171  if(thisStepEnergyDeposit <= 0. || thisStepLength <= 0.)
172  {
173 #ifdef DEBUGSTEP2
174  ATH_MSG_DEBUG(" Invalid hit trivial content");
175 #endif
176  return false;
177  }
178 
179  // Get Step geometrical parameters (first and end)
180  G4StepPoint *thisStepPoint = step->GetPreStepPoint();
181  G4StepPoint *thisStepBackPoint = step->GetPostStepPoint();
182  G4ThreeVector startPoint = thisStepPoint->GetPosition();
183  G4ThreeVector endPoint = thisStepBackPoint->GetPosition();
184 
185 #ifdef DEBUGSTEP
186  ATH_MSG_DEBUG(" Beginning step position "
187  << startPoint.x() << " " << startPoint.y() << " " << startPoint.z());
188 #endif
189 
190  // find zside from volume name
191  G4int zSide = 1;
192  if (!m_testbeam) {
193  const G4NavigationHistory* g4navigation = thisStepPoint->GetTouchable()->GetHistory();
194  G4int ndep = g4navigation->GetDepth();
195  for (G4int ii=0;ii<=ndep;ii++) {
196  G4VPhysicalVolume* v1 = g4navigation->GetVolume(ii);
197  G4String vname = v1->GetName();
198  if ( vname.find("NegPhysical") != std::string::npos) zSide=-1;
199  }
200  }
201 
202 
203  // BACK directly into the LOCAL half_Barrel Z > 0. PART (mother "stac_phys1")
204 
205  const G4AffineTransform transformation =
206  thisStepPoint->GetTouchable()->GetHistory()->GetTopTransform();
207 
208  G4ThreeVector startPointinLocal =
209  transformation.TransformPoint(startPoint);
210  G4ThreeVector endPointinLocal =
211  transformation.TransformPoint (endPoint);
212 
213 #ifdef DEBUGSTEP
214  ATH_MSG_DEBUG(" Local beginning step position "
215  << startPointinLocal.x() << " " << startPointinLocal.y() << " "
216  << startPointinLocal.z());
217  ATH_MSG_DEBUG(" Local end step position "
218  << endPointinLocal.x() << " " << endPointinLocal.y() << " "
219  << endPointinLocal.z());
220 #endif
221 
222  G4double energy = step->GetTotalEnergyDeposit() * step->GetTrack()->GetWeight(); // Despite the name, this is only ionization.
223 
224  if (m_BirksLaw) {
225  const double EField = 10.; // kV/cm, assume constant for now
226  const double wholeStepLengthCm = step->GetStepLength() / CLHEP::cm;
227  energy = (*m_birksLaw)(energy, wholeStepLengthCm, EField);
228  }
229 
230 
231  // compute number of sub steps
232  // = 1 if no charge collection
233  // otherwise 200 microns (dstep) division
234 
235  G4int nsub_step=1;
236  if (m_IflCur) nsub_step=(int) (thisStepLength/m_dstep) + 1;
237  // delta is fraction of step between two sub steps
238  G4double delta=1./((double) nsub_step);
239 #ifdef DEBUGSTEP
240  ATH_MSG_DEBUG(" nsub_step,delta " << nsub_step << " " << delta);
241 #endif
242 
243  energy /= ((float) (nsub_step)); // Divide into substeps.
244 
245  // loop over sub steps
246 
247  for (G4int i=0;i<nsub_step;i++) {
248 
249  bool Xtalk = false;
250 
251  G4double fraction=(((G4double) i)+0.5)*delta;
252  G4ThreeVector subinLocal=startPointinLocal*(1-fraction) + endPointinLocal*fraction;
253  G4double xloc = subinLocal.x();
254  G4double yloc = subinLocal.y();
255  G4double zloc = subinLocal.z();
256  G4double etaloc = subinLocal.pseudoRapidity();
257  G4double philoc = subinLocal.phi();
258  if(philoc<0.) philoc = philoc + 2.*M_PI;
259  G4double radloc = sqrt( xloc*xloc + yloc*yloc );
260 #ifdef DEBUGSTEP
261  ATH_MSG_DEBUG(" local position sub_step "
262  << xloc << " " << yloc << " " << zloc);
263 #endif
264 
265  // apply fiducial cuts
266  if (!FiducialCuts(radloc,zloc,etaloc)) {
267 #ifdef DEBUGSTEP
268  ATH_MSG_DEBUG("LArBarrelCalculator: outside fiducial cuts");
269 #endif
270  continue;
271  }
272  LArG4::Barrel::CalcData currentCellData;
273  m_geometry->findCell(currentCellData,xloc,yloc,zloc,radloc,etaloc,philoc,m_IflCur);
274 
275  if (currentCellData.cellID == 0)
276  {
277 #ifdef DEBUGSTEP
278  ATH_MSG_DEBUG("LArBarrelCalculator: Invalid hit CELLID == 0 ");
279  ATH_MSG_DEBUG("x,y,z local " << xloc << " " << yloc << " " << zloc);
280  ATH_MSG_DEBUG("radius " << radloc <<" etaloc "<< etaloc << " philoc " << philoc);
281 #endif
282  continue;
283  }
284  G4int region = currentCellData.region;
285  G4int etaBin = currentCellData.etaBin;
286  G4int phiBin = currentCellData.phiBin;
287  G4int sampling = currentCellData.sampling;
288 
289  if( zSide == -1 )
290  {
291  // following code for an Y-axis rotation to define Z < 0. Barrel part
292  if( sampling == 1 && region ==0 )
293  {
294  phiBin = 31 - phiBin;
295  if(phiBin < 0 ) phiBin += 64;
296  }
297  if( sampling == 1 && region ==1 )
298  {
299  phiBin = 127 - phiBin;
300  if(phiBin < 0 ) phiBin += 256;
301  }
302  if( sampling >= 2 )
303  {
304  phiBin = 127 - phiBin;
305  if(phiBin < 0 ) phiBin += 256;
306  }
307  }
308 #ifdef DEBUGSTEP
309  ATH_MSG_DEBUG(" region,side,sampling,eta,phi " << region << " " << zSide << " "
310  << sampling << " " << etaBin << " " << phiBin);
311  ATH_MSG_DEBUG(" distance to electrode,abs " << currentCellData.distElec << " "
312  << currentCellData.distAbs);
313  ATH_MSG_DEBUG(" local coordinates " << currentCellData.x0 << " " << currentCellData.y0);
314 #endif
315 
316  if (std::fabs(currentCellData.distElec)< m_ThickEle ||
317  std::fabs(currentCellData.distAbs) < m_ThickAbs) {
318 #ifdef DEBUGSTEP
319  ATH_MSG_DEBUG(" hit in absorber or electrode radius:" << radloc);
320 #endif
321  continue;
322  }
323 
324  identifier2.clear();
325  identifier2 << 4 // LArCalorimeter
326  << 1 // LArEM
327  << zSide
328  << sampling
329  << region
330  << etaBin
331  << phiBin;
332 
333  // time computation is not necessarily correct for test beam
334  // G4double time;
335  // if (m_testbeam)
336  // {
337  // time=0.;
338  // }
339  // else
340  // {
341  // const G4double tof = thisStepPoint->GetGlobalTime() / Units::ns;
342  // time = tof - ( thisStepPoint->GetPosition().mag()/CLHEP::c_light ) / Units::ns;
343  // }
344 
345  const G4double time = (m_testbeam)? 0.0 :
346  ( thisStepPoint->GetGlobalTime() - ( thisStepPoint->GetPosition().mag()/CLHEP::c_light ) ) / Units::ns;
347 
348 #ifdef DEBUGSTEP
349  ATH_MSG_DEBUG(" Energy for sub step " << energy);
350 #endif
351 
352  G4double Current;
353  G4double Current_xt1,Current_xt2;
354  Current_xt1=0;
355  Current_xt2=0;
356  if (!m_IflCur) {
357  // no charge collection Current=E from Geant
358  Current=energy;
359  }
360  else {
361  // full charge collection
362  G4double xmap,ymap;
363  G4int nfold = currentCellData.nfold;
364  G4double x0=currentCellData.x0;
365  G4double y0=currentCellData.y0;
366  if (x0<1500 || x0>1960 || y0>30 || y0<-30) {
367  ATH_MSG_WARNING("weird x0,y0 " << x0 << " " << y0);
368  }
369 #ifdef DEBUGSTEP
370  G4double rr = sqrt(x0*x0+y0*y0);
371  ATH_MSG_DEBUG(" radius,rad0 " << radloc << " " << rr);
372 #endif
373  const CurrMap* mapOfCurrent(nullptr);
374  bool UseFold=false;
375  // Are we close to a fold ? (fold 0 has some pathology)
376  if ((x0 > m_accmap->GetXmin(nfold) || nfold==0) &&
377  x0 < m_accmap->GetXmax(nfold) &&
378  y0 > m_accmap->GetYmin(nfold) &&
379  y0 < m_accmap->GetYmax(nfold) &&
380  (nfold != 13 || x0 < 1957.5) &&
381  (nfold>0 || x0 < 1504.6) ) {
382  xmap=x0;
383  ymap=y0;
384 #ifdef DEBUGSTEP
385  ATH_MSG_DEBUG(" Map for fold xmap,ymap " << nfold << " " << xmap << " " << ymap);
386 #endif
387  UseFold=true;
388  G4int sampMap = currentCellData.sampMap;
389  G4int etaMap = currentCellData.etaMap;
390  mapOfCurrent = m_accmap->GetMap(nfold,region,sampMap,etaMap);
391  // catch problem to find map
392  if (!mapOfCurrent) {
393  ATH_MSG_WARNING(" Problem to access map fold = " << nfold);
394  ATH_MSG_WARNING(" region,sampling,eta,fold " << region << " " << sampMap << " "
395  << etaMap << " " << nfold);
396  return false;
397  }
398  }
399  else {
400  G4int n;
401  G4int nstraight = currentCellData.nstraight;
402  if (nstraight%2==0) n=22;
403  else n=21;
404  mapOfCurrent = m_accmap->GetMap(n,region,sampling,etaBin);
405  // catch problem to find map
406  if (!mapOfCurrent) {
407  ATH_MSG_WARNING(" Problem to access map straight = " << nstraight);
408  return false;
409  }
410  xmap = currentCellData.xl;
411  ymap = currentCellData.distElec;
412  // special case for first straight section, which is shorter
413  if (nstraight==0) xmap = 0.5*(xmap+1.);
414 #ifdef DEBUGSTEP
415  ATH_MSG_DEBUG(" Map for straight xl,delec " << xmap << " " << ymap);
416 #endif
417  } // fold or straight
418  double gap;
419  double current0,current1,current2;
420  // get current for elementary charge
421  mapOfCurrent->GetAll(xmap,ymap,&gap,&current0,&current1,&current2);
422  G4double gap2=std::fabs(currentCellData.distElec)+std::fabs(currentCellData.distAbs)
424 
425  // in which HV cell are we ?
426  int ipm,ielec,ieta,iside;
427  if (zSide==1) ipm=1; // A side
428  else ipm=0; // C side
429  ielec=currentCellData.phiGap;
430  if (zSide==-1) {
431  ielec = 511 - ielec;
432  if(ielec < 0 ) ielec += 1024;
433  }
434  ieta=((int) (etaloc*(1./0.2)));
435  if (ieta>6) ieta=6; //part 1.4 to 1.475 is same HV as 1.2 to 1.4
436  iside=0; // phi lower than electrode 0, 1 for phi higher than electrode
437  if ((currentCellData.distElec>0 && zSide==1)
438  || (currentCellData.distElec<0 && zSide==-1) ) iside=1;
439 
440  // HV extrapolation
441  double current;
442  double hv=m_hv[ipm][ielec][ieta][iside];
443  if (hv>1995.) current=current0;
444  else if (hv>5.) current=ScaleHV(hv,current0,current1,current2);
445  else current=0.;
446 
447  // extrapolation for non nominal gap (allows to include sagging effect)
448  // i ~ (gap/gap2)**1.3
449  // gap = nominal gap from current map
450  // gap2 = real gap from geometry
451  // dgap = gap/gap2 -1
452  // at first order i ~ (1+1.3*dgap)
453  double dgap=0;
454  if (gap>1e-3 && gap2 >1e-3) dgap=gap/gap2-1;
455  current = current * (1. + 1.3*dgap);
456 
457 #ifdef DEBUGSTEP
458  ATH_MSG_DEBUG(" elementary current " << current0);
459  ATH_MSG_DEBUG(" Gap from Map/calculator " << gap << " " << gap2);
460 #endif
461 
462  Current = energy*current;
463 
464  // check if pathology...
465  if (!UseFold && std::fabs(currentCellData.distElec)>2.1 && current0 < 0.1) {
466  ATH_MSG_WARNING(" xl,distEle " << currentCellData.xl << " "
467  << currentCellData.distElec
468  << " str number " << currentCellData.nstraight
469  << " sampling,eta " << sampling << " " << etaBin << " "
470  << " current/E " << current0);
471  }
472 
473  // compute effect around transition at eta=0.8 from electric field
474  // read from map weighting factor ( E**1.3 = E*E**0.3)
475  // in x +-9mm around transition (assume symmetry around 0)
476  // in y distance from electrode in gap
477  bool InTrans=false;
478  //double Current_test=Current;
479  if (m_IflMapTrans) {
480  float etaTrans=0.8;
481  if (fabs(etaloc-etaTrans) < 0.025) {
482  double x=std::fabs(zloc-radloc*sinh(etaTrans))/cosh(etaTrans);
483  double y=std::fabs(currentCellData.distElec);
484  if ( x < m_etamap3->Xmax() ) {
485  double resp;
486  m_etamap3->GetData0(x,y,&resp);
487  Current = Current*resp;
488  InTrans=true;
489  }
490  } // eta = 0.8 +- 0.025
491  } // if m_IflMapTrans
492 
493  // simulate cross-talk effects and transitions in eta between cells
494  // (only in region 0, samplings 1 and 2)
495 
496  if (region==0) {
497 
498  double resp,xt0,xt1,xt2,deta;
499  if (sampling==1) {
500  deta=etaloc-0.003125*((double)etaBin+0.5);
501  m_etamap1->GetData(std::fabs(deta),std::fabs(currentCellData.distElec),
502  &resp,&xt0,&xt1,&xt2);
503 #ifdef DEBUGSTEP
504  ATH_MSG_DEBUG("hit in strip etaloc,etaBin,deta,delec,resp,xt0,xt1,xt2 "
505  << etaloc << " " << etaBin << " " << deta*1000 << " " << currentCellData.distElec
506  << " " << resp << " " << xt0 << " " << xt1 << " " << xt2);
507 #endif
508  if (!InTrans) Current = Current*resp;
509  if (m_IflXtalk && etaBin > 1 && etaBin < 446) {
510  Xtalk=true;
511  if (deta>0) {
512  identifier_xt1.clear();
513  identifier_xt1 << 4 << 1 << zSide << sampling << region << (etaBin+1) << phiBin;
514  Current_xt1 = Current*xt1;
515  identifier_xt2.clear();
516  identifier_xt2 << 4 << 1 << zSide << sampling << region << (etaBin-1) << phiBin;
517  Current_xt2 = Current*xt2;
518  }
519  else {
520  identifier_xt1.clear();
521  identifier_xt1 << 4 << 1 << zSide << sampling << region << (etaBin-1) << phiBin;
522  Current_xt1 = Current*xt1;
523  identifier_xt2.clear();
524  identifier_xt2 << 4 << 1 << zSide << sampling << region << (etaBin+1) << phiBin;
525  Current_xt2 = Current*xt2;
526  }
527  Current = Current*xt0;
528  } // m_IflXtalk = true
529  }
530  else if (sampling==2 && !InTrans) {
531  deta=etaloc-0.025*((double)etaBin+0.5);
532  m_etamap2->GetData0(std::fabs(deta),std::fabs(currentCellData.distElec),
533  &resp);
534 #ifdef DEBUGSTEP
535  ATH_MSG_DEBUG("hit in middle etaloc,etaBin,deta,delec,resp,xt0,xt1,xt2 "
536  << etaloc << " " << etaBin << " " << deta*1000 << " " << currentCellData.distElec
537  << " " << resp);
538 #endif
539  Current = Current*resp;
540  } // sampling =1 or 2
541 
542  } // region=0
543 
544  } // switch for current simulation
545 
546 
547  // check if we have a new hit in a different cell, or if we add this substep
548  // to an already existing hit
549  G4bool found=false;
550  for (unsigned int i=0; i<hdata.size(); i++) {
551  if (hdata[i].id==identifier2) {
552  hdata[i].energy += Current;
553  hdata[i].time += time*Current;
554  found=true;
555  break;
556  }
557  } // loop over hits
558  if (!found) {
559  hdata.emplace_back(LArHitData{identifier2, time*Current, Current});
560  } // hit was not existing before
561 
562  if (Xtalk) {
563  for (unsigned int i=0; i<hdata.size(); i++) {
564  if (hdata[i].id==identifier_xt1) {
565  hdata[i].energy += Current_xt1;
566  hdata[i].time += time*Current_xt1;
567  found=true;
568  break;
569  }
570  } // loop over hits
571  if (!found) {
572  hdata.emplace_back(LArHitData{identifier_xt1, time*Current_xt1, Current_xt1});
573  }
574  found=false;
575  for (unsigned int i=0; i<hdata.size(); i++) {
576  if (hdata[i].id==identifier_xt2) {
577  hdata[i].energy += Current_xt2;
578  hdata[i].time += time*Current_xt2;
579  found=true;
580  break;
581  }
582  } // loop over hits
583  if (!found) {
584  hdata.emplace_back(LArHitData{identifier_xt2, time*Current_xt2, Current_xt2});
585  }
586  } // Xtalk true
587 
588 
589  } // *** End of loop over sub steps
590 
591 #ifdef DEBUGSTEP
592  ATH_MSG_DEBUG("Number of hits for this step " << m_nhits << " "
593  << hdata.size());
594 #endif
595 
596  // finalise time computations
597  for (unsigned int i=0;i<hdata.size();i++) {
598  if (std::fabs(hdata[i].energy)>1e-6) hdata[i].time=hdata[i].time/hdata[i].energy;
599  else hdata[i].time=0.;
600 #ifdef DEBUGSTEP
601  ATH_MSG_DEBUG("Hit Energy/Time "
602  << hdata[i].energy << " " << hdata[i].time);
603 #endif
604  }
605 
606  if (hdata.size()>0) return true;
607  return false;
608 }
609 
610 // ===============================================================================
611 // Cuts to define active region of accordion calorimeter
612 // 1500.024 < r < 1960.00 mm
613 // |eta| < 1.475
614 // 4 < z < 3164 mm (in local half barrel coordinates)
615 
616 G4bool LArBarrelCalculator::FiducialCuts(G4double radloc,G4double zloc,G4double etaloc) const
617 {
618  if (radloc < m_rMinAccordion ||
619  radloc > m_rMaxAccordion ||
620  etaloc > m_etaMaxBarrel ||
621  zloc < m_zMinBarrel ||
622  zloc > m_zMaxBarrel) return false;
623  else return true;
624 }
625 
626 // ==========================================================================
627 // HV values
628 // set all to 2000V. This should be changed if one wants to simulate
629 // some HV imperfections
631 {
632  ATH_MSG_DEBUG(" **** in LArBarrelCalculator::InitHV() ");
633 
634 
635 
636 
637  float defaultHvVal=2000.;
638  ATH_MSG_DEBUG(" defaultHvVal " << defaultHvVal);
639  for (int ipm=0;ipm<2;ipm++) {
640  for (int ielec=0;ielec<1024;ielec++) {
641  for (int ieta=0;ieta<7;ieta++) {
642  for (int iside=0;iside<2;iside++) {
643  m_hv[ipm][ielec][ieta][iside] = defaultHvVal;
644  }
645  }
646  }
647  }
648 
649  if (m_doHV) {
650  // initialize services
651  SmartIF<StoreGateSvc> pDetStore{Gaudi::svcLocator()->service("DetectorStore")};
652  if (!pDetStore) {
653  ATH_MSG_WARNING("LArBarrelCalculator::InitHV() unable to get Detector Store! Use default HV values.");
654  return;
655  }
656 
657  // get EMBHV Manager
658  const LArHVManager *manager = nullptr;
659  if (pDetStore->retrieve(manager)==StatusCode::SUCCESS) {
660  const EMBHVManager& hvManager=manager->getEMBHVManager();
661  const EMBHVManager::EMBHVData hvdata = hvManager.getDataSim();
662  ATH_MSG_DEBUG(" got HV Manager ");
663  // loop over HV modules
664  for (unsigned int iSide=0;iSide<2;iSide++) {
665  for (unsigned int iPhi=0;iPhi<16;iPhi++) {
666  for (unsigned int iSector=0;iSector<2;iSector++) {
667  for (unsigned int iEta=0;iEta<7;iEta++) {
668  const EMBHVModule& hvMod = hvManager.getHVModule(iSide,iEta+1,iPhi,iSector);
669  for (unsigned int ielec=0;ielec<32;ielec++) {
670  const EMBHVElectrode& electrode = hvMod.getElectrode(ielec);
671  unsigned jElec = ielec+32*iSector+64*iPhi;
672  for (unsigned int iGap=0;iGap<2;iGap++) {
673  double hv = hvdata.voltage (electrode, iGap);
674  ATH_MSG_DEBUG(" iSide,jElec,iEta,iGap,hv " << iSide << " " << jElec << " " << iEta << " " << iGap << " " << hv);
675  if (hv>-999.) m_hv[iSide][jElec][iEta][iGap] = hv;
676  }
677  }
678  }
679  }
680  }
681  }
682  }
683  else {
684  ATH_MSG_WARNING(" Unable to find HV Manager ");
685  }
686  }
687 
688  return;
689 }
690 
691 //==========================================================================
692 // extrapolate response with HV
693 // hv = actual HV
694 // curr0 = response for 2000V, curr1 = for 1000V, curr2 for 400V
695 // assumes resp = a* HV*b between 1000-2000 and 400-1000V
696 // (fixes b=0.57 for HV smaller than 400V)
697 
698 double LArBarrelCalculator::ScaleHV(double hv, double curr0, double curr1, double curr2) const
699 {
700  double b;
701  double resp=0.;
702  if (hv>1000.) {
703  if (std::fabs(curr1)>1e-6) {
704  double x=curr0/curr1;
705  if (x>1e-6) {
706  b=log(x)*(1./(log(2000.)-log(1000.)));
707  resp = curr0*exp(b*(log(hv)-log(2000.)));
708  }
709  }
710  }
711  else if (hv>400.) {
712  if (std::fabs(curr2)>1e-6) {
713  double x=curr1/curr2;
714  if (x>1e-6) {
715  b=log(x)*(1./(log(1000.)-log(400.)));
716  resp = curr1*exp(b*(log(hv)-log(1000.)));
717  }
718  }
719  }
720  else {
721  if (std::fabs(curr2)>1e-6) {
722  b=0.57;
723  resp = curr2*exp(b*(log(hv)-log(400.)));
724  }
725  }
726  return resp;
727 }
LArBarrelCalculator::Process
virtual G4bool Process(const G4Step *a_step, std::vector< LArHitData > &hdata) const override final
Definition: LArBarrelCalculator.cxx:153
LArBarrelCalculator::m_IflXtalk
Gaudi::Property< bool > m_IflXtalk
Definition: LArBarrelCalculator.h:69
AllowedVariables::e
e
Definition: AsgElectronSelectorTool.cxx:37
LArBarrelCalculator::m_geometry
ServiceHandle< ILArBarrelGeometry > m_geometry
Definition: LArBarrelCalculator.h:60
fillPileUpNoiseLumi.current
current
Definition: fillPileUpNoiseLumi.py:52
LArBarrelCalculator::m_etamap2
std::unique_ptr< MapEta > m_etamap2
Definition: LArBarrelCalculator.h:63
EMBHVElectrode
Definition: EMBHVElectrode.h:15
CurrMap::GetAll
void GetAll(double x, double y, double *gap, double *curr0, double *curr1, double *curr2) const
Definition: CurrMap.cxx:93
LArHVManager.h
LArG4BirksLaw.h
LArG4Identifier
Definition: LArG4Identifier.h:121
LArBarrelCalculator::m_ThickEle
double m_ThickEle
Definition: LArBarrelCalculator.h:85
python.SystemOfUnits.mm
float mm
Definition: SystemOfUnits.py:98
LArCalculatorSvcImp::m_Birksk
Gaudi::Property< double > m_Birksk
Definition: LArCalculatorSvcImp.h:27
LArBarrelCalculator::m_NCellTot
int m_NCellTot
Definition: LArBarrelCalculator.h:87
LArGeo::VDetectorParameters
Definition: VDetectorParameters.h:29
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
LArBarrelCalculator::m_accmap
const AccMap * m_accmap
Definition: LArBarrelCalculator.h:61
LArBarrelCalculator::m_etamap3
std::unique_ptr< MapEta > m_etamap3
Definition: LArBarrelCalculator.h:64
LArBarrelCalculator::m_etamap1
std::unique_ptr< MapEta > m_etamap1
Definition: LArBarrelCalculator.h:62
gridSubmitIDTPM.check
check
Definition: gridSubmitIDTPM.py:45
LArBarrelCalculator::m_IflMapTrans
Gaudi::Property< bool > m_IflMapTrans
Definition: LArBarrelCalculator.h:68
LArBarrelCalculator::m_etaMaxBarrel
double m_etaMaxBarrel
Definition: LArBarrelCalculator.h:77
LArNoisyROSummNtuple.hv
bool hv
Definition: LArNoisyROSummNtuple.py:185
LArBarrelCalculator::m_zMinBarrel
double m_zMinBarrel
Definition: LArBarrelCalculator.h:78
LArBarrelCalculator::m_hv
double m_hv[2][1024][7][2]
Definition: LArBarrelCalculator.h:100
LArG4Identifier::clear
void clear()
M_PI
#define M_PI
Definition: ActiveFraction.h:11
LArHitData
Definition: ILArCalculatorSvc.h:23
LArVG4DetectorParameters.h
LArBarrelCalculator::m_ThickAbs
double m_ThickAbs
Definition: LArBarrelCalculator.h:84
LArG4::Barrel::CalcData
Definition: ILArBarrelGeometry.h:26
LArBarrelCalculator::m_zMaxBarrel
double m_zMaxBarrel
Definition: LArBarrelCalculator.h:79
LArG4::Barrel::CalcData::phiGap
G4int phiGap
Definition: ILArBarrelGeometry.h:33
drawFromPickle.exp
exp
Definition: drawFromPickle.py:36
LArG4::Barrel::CalcData::x0
G4double x0
Definition: ILArBarrelGeometry.h:39
x
#define x
LArBarrelCalculator::InitHV
void InitHV()
Definition: LArBarrelCalculator.cxx:630
LArG4::Barrel::CalcData::xl
G4double xl
Definition: ILArBarrelGeometry.h:38
CaloSwCorrections.gap
def gap(flags, cells_name, *args, **kw)
Definition: CaloSwCorrections.py:212
LArBarrelCalculator::m_dstep
Gaudi::Property< double > m_dstep
Definition: LArBarrelCalculator.h:71
EMBHVElectrode.h
LArBarrelCalculator::m_NCellMax
int m_NCellMax
Definition: LArBarrelCalculator.h:88
LArBarrelCalculator::initialize
virtual StatusCode initialize() override final
Definition: LArBarrelCalculator.cxx:52
LArBarrelCalculator::m_testbeam
bool m_testbeam
Definition: LArBarrelCalculator.h:91
LArBarrelCalculator::LArBarrelCalculator
LArBarrelCalculator(const std::string &name, ISvcLocator *pSvcLocator)
Definition: LArBarrelCalculator.cxx:47
LArG4BirksLaw::k
double k() const
Definition: LArG4BirksLaw.h:19
EMBHVManager::getHVModule
const EMBHVModule & getHVModule(unsigned int iSide, unsigned int iEta, unsigned int iPhi, unsigned int iSector) const
Definition: EMBHVManager.cxx:194
cm
const double cm
Definition: Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/FCAL_ChannelMap.cxx:25
LArG4::Barrel::CalcData::cellID
int cellID
Definition: ILArBarrelGeometry.h:27
LArBarrelCalculator::ScaleHV
double ScaleHV(double, double, double, double) const
Definition: LArBarrelCalculator.cxx:698
xAOD::etaBin
setSAddress setEtaMS setDirPhiMS setDirZMS setBarrelRadius setEndcapAlpha setEndcapRadius setInterceptInner setEtaMap etaBin
Definition: L2StandAloneMuon_v1.cxx:149
ParticleGun_FastCalo_ChargeFlip_Config.energy
energy
Definition: ParticleGun_FastCalo_ChargeFlip_Config.py:78
CurrMap
Definition: CurrMap.h:10
lumiFormat.i
int i
Definition: lumiFormat.py:85
EMBHVManager::EMBHVData::voltage
double voltage(const EMBHVElectrode &electrode, const int &iGap) const
Definition: EMBHVManager.cxx:130
LArBarrelCalculator::m_birksLaw
const LArG4BirksLaw * m_birksLaw
Definition: LArBarrelCalculator.h:73
beamspotman.n
n
Definition: beamspotman.py:727
LArG4::Barrel::CalcData::sampling
G4int sampling
Definition: ILArBarrelGeometry.h:28
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
xAOD::etaMap
setSAddress setEtaMS setDirPhiMS setDirZMS setBarrelRadius setEndcapAlpha setEndcapRadius setInterceptInner etaMap
Definition: L2StandAloneMuon_v1.cxx:145
LArG4::Barrel::CalcData::phiBin
G4int phiBin
Definition: ILArBarrelGeometry.h:31
LArBarrelCalculator::m_rMinAccordion
double m_rMinAccordion
Definition: LArBarrelCalculator.h:81
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
LArG4::Barrel::CalcData::nfold
G4int nfold
Definition: ILArBarrelGeometry.h:35
AccMap.h
xAOD::double
double
Definition: CompositeParticle_v1.cxx:159
LArG4::Barrel::CalcData::etaMap
G4int etaMap
Definition: ILArBarrelGeometry.h:42
LArCalculatorSvcImp
Definition: LArCalculatorSvcImp.h:13
EMBHVManager::getDataSim
EMBHVData getDataSim() const
Definition: EMBHVManager.cxx:324
LArG4::Barrel::CalcData::sampMap
G4int sampMap
Definition: ILArBarrelGeometry.h:41
MapEta.h
LArBarrelCalculator::m_rMaxAccordion
double m_rMaxAccordion
Definition: LArBarrelCalculator.h:82
LArG4::Barrel::CalcData::region
G4int region
Definition: ILArBarrelGeometry.h:29
Athena::Units
Definition: Units.h:45
LArCalculatorSvcImp::m_BirksLaw
Gaudi::Property< bool > m_BirksLaw
Definition: LArCalculatorSvcImp.h:23
LArBarrelCalculator.h
EMBHVManager::EMBHVData
Definition: EMBHVManager.h:39
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
xAOD::phiBin
setSAddress setEtaMS setDirPhiMS setDirZMS setBarrelRadius setEndcapAlpha setEndcapRadius setPhiMap phiBin
Definition: L2StandAloneMuon_v2.cxx:145
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:76
LArBarrelCalculator::FiducialCuts
G4bool FiducialCuts(G4double, G4double, G4double) const
Definition: LArBarrelCalculator.cxx:616
checkTriggerxAOD.found
found
Definition: checkTriggerxAOD.py:328
EMBHVManager
This class provides direct access to information on the HV electrodes within the barrels....
Definition: EMBHVManager.h:36
python.PhysicalConstants.c_light
float c_light
Definition: PhysicalConstants.py:73
Units.h
Wrapper to avoid constant divisions when using units.
AccMap::GetMap
const CurrMap * GetMap(int ifold, int ielecregion) const
Definition: AccMap.cxx:92
Trk::iPhi
@ iPhi
Definition: ParamDefs.h:47
LArG4::Barrel::CalcData::etaBin
G4int etaBin
Definition: ILArBarrelGeometry.h:30
LArG4::Barrel::CalcData::distElec
G4double distElec
Definition: ILArBarrelGeometry.h:36
LArG4::Barrel::CalcData::nstraight
G4int nstraight
Definition: ILArBarrelGeometry.h:34
LArG4::Barrel::CalcData::y0
G4double y0
Definition: ILArBarrelGeometry.h:40
LArG4BirksLaw
Definition: LArG4BirksLaw.h:8
AccMap::GetAccMap
static const AccMap * GetAccMap()
Definition: AccMap.cxx:72
LArHVManager
This class provides access to the High Voltage throughout the LAr. High voltage conditions can also b...
Definition: LArHVManager.h:24
y
#define y
python.CaloAddPedShiftConfig.int
int
Definition: CaloAddPedShiftConfig.py:45
CaloSwCorrections.time
def time(flags, cells_name, *args, **kw)
Definition: CaloSwCorrections.py:242
AccMap::GetYmin
float GetYmin(int ifold) const
Definition: AccMap.h:31
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
python.CaloCondTools.log
log
Definition: CaloCondTools.py:20
LArCellBinning.step
step
Definition: LArCellBinning.py:158
physics_parameters.parameters
parameters
Definition: physics_parameters.py:144
EMBHVModule::getElectrode
const EMBHVElectrode & getElectrode(unsigned int iElectrode) const
Definition: EMBHVModule.cxx:69
python.Logging.manager
manager
Definition: PhysicsAnalysis/D3PDTools/AnaAlgorithm/python/Logging.py:92
rr
const boost::regex rr(r_r)
EMBHVModule
Describes one HV Module within the EMB.
Definition: EMBHVModule.h:20
LArBarrelCalculator::m_doHV
Gaudi::Property< bool > m_doHV
Definition: LArBarrelCalculator.h:74
LArG4::Barrel::CalcData::distAbs
G4double distAbs
Definition: ILArBarrelGeometry.h:37
xAOD::iEta
setScale setgFexType iEta
Definition: gFexJetRoI_v1.cxx:77
LArGeo::VDetectorParameters::GetInstance
static const VDetectorParameters * GetInstance()
Definition: VDetectorParameters.cxx:29
StoreGateSvc.h
AccMap::GetXmin
float GetXmin(int ifold) const
Definition: AccMap.h:25
EMBHVModule.h
LArCalculatorSvcImp::m_OOTcut
Gaudi::Property< double > m_OOTcut
Definition: LArCalculatorSvcImp.h:30
EMBHVManager.h
LArBarrelCalculator::m_IflCur
Gaudi::Property< bool > m_IflCur
Definition: LArBarrelCalculator.h:67
python.SystemOfUnits.ns
float ns
Definition: SystemOfUnits.py:146
python.LArMinBiasAlgConfig.float
float
Definition: LArMinBiasAlgConfig.py:65
LArBarrelCalculator::finalize
virtual StatusCode finalize() override final
Definition: LArBarrelCalculator.cxx:146