ATLAS Offline Software
LArBarrelGeometry.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 /********************************************************************
6 
7 NAME: LArBarrelGeometry.cxx
8 PACKAGE: offline/LArCalorimeter/LArG4/LArG4Barrel
9 
10 AUTHORS: G. Unal, L. Carminati
11 CREATED: September, 2004
12 
13 PURPOSE: 'geometrical' methods used by the LArBarrelCalculator.
14  These methods (previously in LArBarrelCalculator) were written
15  by Gaston Parrour and adapted by Sylvain Negroni.
16 
17 UPDATES: - Calculate identifier method used by CalibrationCalculator.
18  (sept 2004)
19  - Cleanup (GU March-April 2005)
20 
21 ********************************************************************/
22 
23 // #define DEBUGHITS
24 
25 #include <cmath>
26 #include <iostream>
27 #include <vector>
28 #include "LArBarrelGeometry.h"
29 
30 #include "LArStraightAbsorbers.h"
31 #include "LArStraightElectrodes.h"
32 #include "LArCoudeElectrodes.h"
33 #include "LArCoudeAbsorbers.h"
34 
35 // values of the radial separations between samplings
36 #include "LArBarrelSampling.h" // Rmax1, Rmax2
37 
38 
39 namespace LArG4 {
40 
41  namespace Barrel {
42 
43  Geometry::Geometry(const std::string& name, ISvcLocator *pSvcLocator)
44  : base_class(name, pSvcLocator)
45  {
46  }
47 
48  // ====================================================================================
49 
51  {
52  // initialize the geometry.
53  // Access source of detector parameters.
54 
56 
57  // number of straight sections (should be 14)
58  m_Nbrt = (int) (parameters->GetValue("LArEMBnoOFAccZigs"));
59  // Number of ZIGs + 1 i.e. 15 = number of folds
60  m_Nbrt1 = m_Nbrt + 1;
61  // phi of first absorber
62  m_gam0 = parameters->GetValue("LArEMBAbsPhiFirst");
63  // radius of curvature of neutral fiber in the folds
64  m_rint_eleFib = parameters->GetValue("LArEMBNeutFiberRadius");
65 
66  m_rc = new double[m_Nbrt1];
67  m_phic = new double[m_Nbrt1];
68  m_delta = new double[m_Nbrt1];
69  m_xc = new double[m_Nbrt1];
70  m_yc = new double[m_Nbrt1];
71 
72  // r,phi positions of the centre of the folds (nominal geometry)
73  for (G4int idat = 0; idat < m_Nbrt1 ; idat++) {
74  m_rc[idat] = (double) parameters->GetValue("LArEMBRadiusAtCurvature",idat);
75  m_phic[idat] = (double) parameters->GetValue("LArEMBPhiAtCurvature",idat);
76  m_delta[idat] = (double) parameters->GetValue("LArEMBDeltaZigAngle",idat);
77  m_xc[idat] = m_rc[idat]*cos(m_phic[idat]);
78  m_yc[idat] = m_rc[idat]*sin(m_phic[idat]);
79  }
80  // define parity of accordion waves: =0 if first wave goes up, 1 if first wave goes down in the local frame
81  m_parity=0;
82  if (m_phic[0]<0.) { m_parity=1; }
83  //
84  m_rMinAccordion = parameters->GetValue("LArEMBRadiusInnerAccordion");
85  m_rMaxAccordion = parameters->GetValue("LArEMBFiducialRmax");
86  m_etaMaxBarrel = parameters->GetValue("LArEMBMaxEtaAcceptance");
87  m_zMinBarrel = parameters->GetValue("LArEMBfiducialMothZmin");
88  m_zMaxBarrel = parameters->GetValue("LArEMBfiducialMothZmax");
89  m_zMaxBarrelDMMargin = 10.0; // 10 mm margin
90  // === GU 11/06/2003 total number of cells in phi
91  // to distinguish 1 module (testbeam case) from full Atlas
92  m_NCellTot = (int) (parameters->GetValue("LArEMBnoOFPhysPhiCell"));
93  // total number of cells in phi to distinguish 1 module (testbeam case) from full Atlas
94  m_testbeam=false;
95  if (m_NCellTot != 1024) {
96  m_testbeam=true;
97  }
98  m_NCellMax=1024;
99  // ===
100 
101  // Initialize r-phi reference map
102  this->GetRphi();
103 
104  if (m_detectorName.empty()) m_ecamName = "LAr::EMB::ECAM";
105  else m_ecamName = m_detectorName+"::LAr::EMB::ECAM";
106 
107 
108  return StatusCode::SUCCESS;
109  }
110 
111  // ====================================================================================
112 
114  {
115  // get pointers to access G4 geometry
120  }
121 
122  // ====================================================================================
123 
125  {
126  if (m_rc) delete [] m_rc;
127  if (m_phic) delete [] m_phic;
128  if (m_delta) delete [] m_delta;
129  if (m_xc) delete [] m_xc;
130  if (m_yc) delete [] m_yc;
131 
132  return StatusCode::SUCCESS;
133  }
134 
135  //======================================================================================
136  //
137  // Here INTRINSIC Distance_to_electrode determination (G.P.)
138  //
139  // This retuns an ALGEBRICDistEle value, the distance from electrode
140  //neutral fiber TOWARDS the Sub_Step in LAr (measured on a local perpendicular
141  //vector unit oriented upwards i.e. following increasing Phi values).
142  //
143  // This is done in THE INTRINSIC LOCAL Z > 0. half_barrel part ("stac_phys1")
144  //
145  // inputs: xhit,yhit = x,y positions in local half barrel
146  // PhiCell = electrode number in phi (0 to 1023 for Atlas case)
147  // Num_Straight = number (0 to 13) of the straight section
148  // Num_Coude = number (0 to 14) of closest fold
149  //
150  // output: Function value = algebric distance to electrode
151  // xl = normalized lenght along electrode straight section (between +-1)
152 
153  double Geometry::Distance_Ele(const double & xhit,
154  const double &yhit, const int &PhiCell, int &Num_Straight,
155  const int &Num_Coude, double &xl) const
156  {
157  //
158  // FrameWork is consistent with the one used to PhiCell determination
159  // e.g. it assumes HERE to be the LOCAL one of "stac_phys1",
160  // (mother of ACCordion volumes) from which Z> 0. and Z < 0. half_barrel
161  // parts are then defined.
162  //
163  // One needs POINTERS to Electrode neutral fibers
164  // either for straight parts or for folds
165  //
166  // Fold Center ccoordinates
167  const G4double Xc[2] = { m_coudeelec->XCentCoude(Num_Coude, PhiCell), m_coudeelec->YCentCoude(Num_Coude, PhiCell) };
168  const G4double radfold = sqrt(Xc[0]*Xc[0]+Xc[1]*Xc[1]);
169  const G4double radhit = sqrt(xhit*xhit+yhit*yhit);
170 
171  // check if the assumed straight number is the correct one
172  // (this can be wrong when we are close to a fold and there is sagging)
173  if (Num_Coude == Num_Straight && radhit <radfold) {
174  if (Num_Straight>0) { Num_Straight = Num_Straight-1; }
175  // ATH_MSG_VERBOSE("radhit,radfold " << radhit << " " << radfold << " change straight by +1");
176  }
177  if (Num_Coude == (Num_Straight+1) && radhit > radfold) {
178  if (Num_Straight<12) { Num_Straight = Num_Straight+1; }
179  // ATH_MSG_VERBOSE("radhit,radfold " << radhit << " " << radfold << " change straight by -1");
180  }
181 
182  // u unit 2D_Vector along straight part of the electrode neutral fiber
183  const double u[2] = { m_electrode->Cosu(Num_Straight, PhiCell), m_electrode->Sinu(Num_Straight, PhiCell) };
184  // Middle m_coordinates of this straight part of the electrode neutral fiber
185  const double Xm[2] = { m_electrode->XCentEle(Num_Straight, PhiCell), m_electrode->YCentEle(Num_Straight, PhiCell) };
186  // m_Hit Vector components
187  double dx = xhit - Xm[0];
188  double dy = yhit - Xm[1];
189 
190  // First compute algebric distance m_hit (2D) the 2D_projection of the
191  // m_Hit Vector on this electrode neutral fiber.
192  const double hit = dx*u[0] + dy*u[1];
193 
194  //
195  // Flat of Fold Region ?
196  //
197  const G4double Half_Elec(m_electrode->HalfLength(Num_Straight,PhiCell));
198 
199  if(std::fabs(hit) < Half_Elec) {
200  // Flat Region
201  xl=hit/Half_Elec;
202  return u[0]*dy - u[1]*dx;
203  }
204  else {
205  // Fold region
206  // c_Hit Vector components and its length
207  dx = xhit - Xc[0];
208  dy = yhit - Xc[1];
209  const double dr = sqrt( dx*dx + dy*dy);
210  if (Num_Coude==Num_Straight) { xl=-1.; }
211  else xl=+1;
212  return (Num_Coude%2 == m_parity) ? (m_rint_eleFib-dr) : (dr - m_rint_eleFib);
213  } // end of Fold Regions
214  } // end of the function Distance_Ele
215 
216 
217  //======================================================================================
218  // Algebric distance to absorber
219  //
220  // inputs: xhit,yhit = x,y positions in local half barrel
221  // PhiCell = absorber number in phi (0 to 1023 for Atlas case)
222  // Num_Straight = number (0 to 13) of the straight section
223  // Num_Coude = number (0 to 14) of closest fold
224  //
225  // output: Function value = algebric distance to electrode
226 
227  double Geometry::Distance_Abs(const double & xhit,
228  const double &yhit, const int &PhiCell, const int &Num_Straight,
229  const int &Num_Coude) const
230  {
231  //
232  // FrameWork is consistent with the one used to PhiCell determination
233  // e.g. it assumes HERE to be the LOCAL one of "stac_phys1",
234  // (mother of ACCordion volumes) from which Z> 0. and Z < 0. half_barrel
235  // parts are then defined.
236  //
237  // One needs POINTERS to Electrode neutral fibers
238  // either for straight parts or for folds
239  //
240  // u unit 2D_Vector along straight part of the electrode neutral fiber
241  const G4double u[2] = { m_absorber->Cosu(Num_Straight, PhiCell), m_absorber->Sinu(Num_Straight, PhiCell) };
242  // Middle m_coordinates of this straight part of the electrode neutral fiber
243  const G4double Xm[2] = { m_absorber->XCentAbs(Num_Straight, PhiCell), m_absorber->YCentAbs(Num_Straight, PhiCell) };
244  // m_Hit Vector components
245  double dx = xhit - Xm[0]; double dy = yhit - Xm[1];
246 
247  // First compute algebric distance hit (2D) the 2D_projection of the
248  // m_Hit Vector on this electrode neutral fiber.
249  const double hit = dx*u[0] + dy*u[1];
250 
251  //
252  // Flat of Fold Region ?
253  //
254  if(std::fabs(hit) < m_absorber->HalfLength(Num_Straight,PhiCell)) {
255  // Flat Region
256  return u[0]*dy - u[1]*dx;
257  }
258  else {
259  // Fold Center c_coordinates
260  const G4double Xc[2] = { m_coudeabs->XCentCoude(Num_Coude, PhiCell), m_coudeabs->YCentCoude(Num_Coude, PhiCell) };
261  // c_Hit Vector components and its length
262  dx = xhit - Xc[0];
263  dy = yhit - Xc[1];
264  const double dr = sqrt( dx*dx + dy*dy);
265  return (Num_Coude%2 == m_parity) ? (m_rint_eleFib-dr) : (dr - m_rint_eleFib);
266  } // end of Fold Regions
267  } // end of the function Distance_Abs
268 
269 
270  //=============================================================================
271  // Function SampSeg
272  //
273  // eta-sampling segmentation of barrel calorimeter GU, January 2005
274  // input values: eta,radius in half-barrel frame
275  //
276  // return value of function: true=active area, false=inactive area
277  // return arguments: iregion,isampling,ieta
278  // take into account detailed electrode drawing
279  // with readout strips
280  // isamp2,ieta2 do not take into account
281  // readout strips and can be used to access current
282  // maps.
283  //
284  // iregion=0 (eta<1.4) or 1 (eta=1.4-1.475)
285  // for region 0: isampling = 1 (strips), 2 (middle), 3 (back)
286  // for region 1: isampling = 1 or isampling = 2
287  // ieta= eta cell number
288  // region0,samp1: ieta=1->448 (strip 0 does not exist)
289  // region0,samp2: ieta=0->55
290  // region0,samp3: ieta=0->26 (max eta 1.325)
291  // region1,samp1: ieta=0->2 (deta=0.025)
292  // region1,samp2: ieta=0 (only 1 cell)
293 
294  G4int Geometry::SampSeg(G4double eta, G4double radius, G4double z,
295  G4int& iregion, G4int& isampling, G4int& ieta,
296  G4int& isamp2, G4int& ieta2) const
297  {
298  // Helper struct to hold pre-calculated geometry information
299  struct Geo {
300  G4double Eta_max,R_max_acc,Z_max_acc,R_min_acc,Z_max_lowr,dzdr;
301  G4double zmax1,zmax2,zmax3,zmax4,zmax5,zmax6,zmax7,rmax1,rmax2,rmax3,rmax4;
302  };
303 
304  // Fill it once
305  static const Geo g = []() {
307  Geo g{};
308 
309  // maximum eta barrel 1.475 (at r=1500.024)
310  g.Eta_max = parameters->GetValue("LArEMBMaxEtaAcceptance");
311  // minimum active radius 1500.024
312  g.R_min_acc= parameters->GetValue("LArEMBRadiusInnerAccordion");
313  // maximum active radius 1960.
314  g.R_max_acc = parameters->GetValue("LArEMBFiducialRmax");
315  // maximum active z (before subtracting edge for signal readout)
316  // currently 3150, should be changed in database to become 3164
317  g.Z_max_acc = parameters->GetValue("LArEMBfiducialMothZmax");
318  // minimum radius at z max for active region
319  const G4double R_min_highz=1548.; //FIXME should be taken from database
320 
321  // compute z edge taken by readout strips on the edge
322  const G4double deltaz=7.; // this include copper 6mm + 2*0.5mm empty space on each side
323  g.zmax1=g.Z_max_acc-deltaz;
324  g.zmax2=g.Z_max_acc-2.*deltaz;
325  g.zmax3=g.Z_max_acc-3.*deltaz;
326  g.zmax4=g.Z_max_acc-4.*deltaz;
327  g.zmax5=g.Z_max_acc-5.*deltaz;
328  g.zmax6=g.Z_max_acc-6.*deltaz;
329  g.zmax7=g.Z_max_acc-7.*deltaz;
330  g.rmax1=g.R_max_acc-deltaz;
331  g.rmax2=g.R_max_acc-2.*deltaz;
332  g.rmax3=g.R_max_acc-3.*deltaz;
333  g.rmax4=g.R_max_acc-4.*deltaz;
334 
335  // maximum z at r=1500.024
336  g.Z_max_lowr = sinh(g.Eta_max)*g.R_min_acc;
337  // slope of z vs r edge (which is not projective in eta...)
338  g.dzdr = (g.Z_max_acc-g.Z_max_lowr)/(R_min_highz-g.R_min_acc);
339 
340  // ATH_MSG_VERBOSE("Initialization of SampSet ");
341  // ATH_MSG_VERBOSE(" Rmin/Rmax " << g.R_min_acc << " " << g.R_max_acc);
342  // ATH_MSG_VERBOSE(" Zmax/Zmax_lowR " << g.Z_max_acc << " " << g.Z_max_lowr);
343  // ATH_MSG_VERBOSE(" Rmin_highz " << R_min_highz);
344  // ATH_MSG_VERBOSE(" dzdr " << g.dzdr);
345  return g;
346  }();
347 
348  // inactive thickness between S1 and S2 FIXME should be taken from database
349  const G4double Dr_s12=1.1;
350  const G4double Eta_max_s1=1.4; // maximum eta region 0
351  const G4double Eta_max_s3=1.325; // maximum eta for S3 in region 0
352  const G4double deta=0.025; // basic granularity
353 
354 
355  // iactive = 1 if active region, 0 if region considered as inactive
356  G4int iactive = 1;
357 
358  const G4double aeta=std::fabs(eta);
359 
360  G4double r12=-1.;
361  G4double r23=-1.;
362 
363  // Not used: G4double rmax=Z_max_acc/sinh(aeta);
364 
365  G4int istrip,imid;
366 
367  // eta < 1.4
368 
369  if (aeta<Eta_max_s1) {
370 
371  // get radius for end of strips
372  istrip=(int) (aeta/deta*8.);
373  if (istrip<0 || istrip >=448) {
374  ATH_MSG_ERROR(" Problem aeta,istrip " << aeta << " " << istrip);
375  return 0;
376  }
377  r12=Rmax1[istrip];
378 
379  // get radius for end of middle
380  imid = (int) (aeta/deta);
381  if (imid <0 || imid >=56) {
382  ATH_MSG_ERROR(" Problem aeta,imid " << aeta << " " << imid);
383  return 0;
384  }
385  r23=Rmax2[imid];
386 
387  iregion=0;
388 
389  // strips
390  if (radius <= r12) {
391  isampling=1;
392  ieta=istrip;
393  if (ieta==0) iactive=0;
394  isamp2=1;
395  ieta2=istrip;
396  }
397 
398  // region between strips and middle => not active, same identifier as strips
399  else if (radius < (r12+Dr_s12)) {
400  isampling=1;
401  ieta=istrip;
402  iactive=0;
403  isamp2=1;
404  ieta2=istrip;
405  }
406 
407  else {
408 
409  // eta<1.325, we can be in the back
410  if (aeta<Eta_max_s3) {
411  // radius<r23 we are in the middle
412  if (radius <= r23) {
413  isampling=2;
414  ieta=imid;
415  isamp2=2;
416  ieta2=imid;
417  }
418  // for radius >r23 we have to take care of the readout strips at high z
419  // and attribute some of the energy to other cells
420  else { // radius>r23
421  if (z>g.zmax1) {
422  isampling=2;
423  ieta=55;
424  }
425  else if (z>g.zmax2) {
426  isampling=2;
427  ieta=54;
428  }
429  else if (z>g.zmax3) {
430  isampling=2;
431  ieta=53;
432  }
433  else if (z>g.zmax4) {
434  isampling=3;
435  ieta=26;
436  }
437  else if (aeta<1.3 && z>g.zmax5) {
438  isampling=2;
439  ieta=52;
440  }
441  else if (aeta<1.3 && z>g.zmax6) {
442  isampling=2;
443  ieta=51;
444  }
445  else if (radius>g.rmax4 && z<g.zmax5 && aeta>1.2) {
446  if (radius>g.rmax1) {
447  isampling=2;
448  ieta=51;
449  }
450  else if(radius>g.rmax2) {
451  isampling=3;
452  ieta=25;
453  }
454  else if (radius>g.rmax3) {
455  if (z<g.zmax7) {
456  isampling=2;
457  ieta=50;
458  }
459  else {
460  isampling=3;
461  ieta=25;
462  }
463  }
464  else {
465  if (aeta<1.25) {
466  isampling=2;
467  ieta=49;
468  }
469  else {
470  isampling=3;
471  ieta=25;
472  }
473  }
474  }
475  // normal back cell
476  else {
477  isampling=3;
478  ieta=imid/2;
479  isamp2=3;
480  ieta2=ieta;
481  }
482  isamp2=3;
483  ieta2=imid/2;
484  } // end radius>r23
485  // put into middle energy deposited along readout strips across the back
486  if (isampling==3 && z<g.zmax4 && (radius<g.rmax4 || aeta<1.2) ) {
487  const double etastr = (imid%2==0) ? 0.025*imid : 0.025*(imid+1);
488  const double delta=radius*(sinh(etastr)-sinh(aeta))/cosh(etastr);
489  double deltastr;
490  if (aeta<0.475) { deltastr=1.5;}
491  else if (aeta<0.80) { deltastr=2.75;}
492  else if (aeta<0.85) { deltastr=1.5;}
493  else if (aeta<1.1) { deltastr=2.75;}
494  else { deltastr=3.25;}
495 
496  if (std::fabs(delta)<deltastr) {
497  isampling=2;
498  ieta=imid;
499  }
500  } // end if sampling==3
501  } // end if eta<1.325
502  else {
503  isampling=2;
504  ieta=imid;
505  if (z>g.zmax1) {
506  ieta=55;
507  }
508  else if (z>g.zmax2 && aeta<1.375) {
509  ieta=54;
510  }
511  isamp2=2;
512  ieta2=imid;
513  } // end eta>1.352
514  } // end radius selection
515  } // end eta1.4
516 
517  // eta between 1.4 and 1.475
518 
519  if (aeta>=Eta_max_s1 && aeta<g.Eta_max) {
520  r12 = Rmax1[447]; // radius for end of sampling 1
521  r23=g.Z_max_acc/sinh(aeta); // radius of end of sampling 2, bounded by high z end
522 
523  const double zmax = g.Z_max_lowr + g.dzdr*(radius-g.R_min_acc);
524 
525  iregion=1;
526  if (radius <=r12) {
527  isampling=1;
528  ieta=int((aeta-Eta_max_s1)/deta);
529  if (z>zmax) { iactive=0; }
530  }
531  else if (radius < (r12+Dr_s12)) {
532  isampling=1;
533  ieta=int((aeta-Eta_max_s1)/deta);
534  iactive=0;
535  }
536  else if (radius <= r23) {
537  isampling=2;
538  ieta=0;
539  if (z>zmax) { iactive=0; }
540  }
541  else {
542  isampling=2;
543  ieta=0;
544  iactive=0;
545  }
546  isamp2=isampling;
547  ieta2=ieta;
548  }
549  // eta above 1.475, not fiducial region, but still returns something
550  // for calibration hits
551  if (aeta>g.Eta_max) {
552  iregion=1;
553  r12 = Rmax1[447];
554  if (radius <=r12) {
555  isampling=1;
556  ieta=2;
557  }
558  else {
559  isampling=2;
560  ieta=0;
561  }
562  isamp2=isampling;
563  ieta2=ieta;
564  iactive=0;
565  }
566 
567  // cross-check of active region
568  if (z>g.Z_max_acc || radius>g.R_max_acc || radius<g.R_min_acc || aeta > g.Eta_max) iactive=0;
569 
570  return iactive;
571  }
572  // =======================================================================
573  // function findCell
574  //
575  // compute cell in EM accordion for hit at position x,y,z,radius,eta,phi
576  // given in LOCAL half barrel coordinate system (Stac Geant volume)
577  // It has already been checked that the hit is in the accordion sensitive volume
578  //
579 
580  void Geometry::findCell(CalcData & currentCellData,
581  const double &xPosition,
582  const double &yPosition,
583  const double &zPosition,
584  const double &aRadius,
585  const double &anEta,
586  const double &/*aPhi*/,
587  const bool MapDetail) const
588  {
589 
590  currentCellData.cellID = 0;
591 
592  if (aRadius < m_rc[0] || aRadius >= m_rc[m_Nbrt1-1]) {
593 #ifdef DEBUGHITS
594  ATH_MSG_VERBOSE(" Outside Accordion " << aRadius << " " << m_rc[0] << " " << m_rc[m_Nbrt1-1]);
595 #endif
596  return; // outside accordion
597  }
598 
599  // set the straight section number
600  currentCellData.nstraight=0;
601  for (int i=1;i<m_Nbrt1;i++) {
602  if (m_rc[i] > aRadius) { break; }
603  currentCellData.nstraight++;
604  }
605  if (currentCellData.nstraight <0 || currentCellData.nstraight >= m_Nbrt) {
606  ATH_MSG_ERROR("Invalid straight number " << currentCellData.nstraight << " " << aRadius);
607  return;
608  }
609 
610  // get the closest fold number
611  currentCellData.nfold=currentCellData.nstraight;
612  if (std::fabs(aRadius-m_rc[currentCellData.nfold]) > std::fabs(aRadius-m_rc[currentCellData.nfold+1]) ) {
613  currentCellData.nfold +=1;
614  }
615  if (currentCellData.nfold <0 || currentCellData.nfold >= m_Nbrt1) {
616  ATH_MSG_ERROR("Invalid fold number " << currentCellData.nfold);
617  return;
618  }
619 
620 
621 #ifdef DEBUGHITS
622  ATH_MSG_VERBOSE(" BarrelGeometry: radius,eta,phi " << aRadius << " " << anEta << " ");
623  ATH_MSG_VERBOSE(" Straight/Fold numbers " << currentCellData.nstraight << " " << currentCellData.nfold);
624 #endif
625 
626  // eta and longitudinal segmentations
627  G4int ireg,isamp,ieta,isamp2,ieta2;
628  currentCellData.cellID = this->SampSeg(anEta,aRadius,zPosition,ireg,isamp,ieta,isamp2,ieta2);
629 
630  currentCellData.etaBin = ieta;
631  currentCellData.sampling = isamp;
632  currentCellData.region = ireg;
633  currentCellData.etaMap = ieta2;
634  currentCellData.sampMap = isamp2;
635 
636  // compute electrode number in phi
637  int phicell = this->PhiGap(aRadius,xPosition,yPosition);
638  if (phicell<0) phicell=0;
639  // for test beam, some protection
640  if (m_NCellTot !=1024) {
641  if (phicell>=m_NCellTot) {
642  if (phicell<512) { phicell=m_NCellTot-1; }
643  else { phicell=0; }
644  currentCellData.cellID=0;
645  }
646  }
647 
648 #ifdef DEBUGHITS
649  ATH_MSG_VERBOSE(" phigap " << phicell);
650 #endif
651 
652  // compute readout cell number
653  int sampling_phi_nGaps=4;
654  if (currentCellData.region==0 && currentCellData.sampling==1) { sampling_phi_nGaps=16; }
655 
656  if (currentCellData.cellID==0) {
657  currentCellData.phiBin = (G4int) ( phicell/sampling_phi_nGaps );
658  currentCellData.distElec=9999.;
659  return;
660  }
661 
662  // compute distance to electrode
663  G4double xl;
664  G4int nstr = currentCellData.nstraight;
665  const G4double distElec = this->Distance_Ele(xPosition,yPosition,phicell,nstr,currentCellData.nfold,xl);
666 
667 #ifdef DEBUGHITS
668  ATH_MSG_VERBOSE(" distElec " << distElec);
669 #endif
670 
671  // if distance is < 2.5mm we are sure to be in the correct gap
672  if (std::fabs(distElec) > 2.5) {
673  // try +-2 electrode in phi to get minimum distance
674  double dElecMin=distElec;
675  double xlmin=xl;
676  int phicellmin=phicell;
677  for (int ii=-2;ii<3;ii++) {
678  if (ii==0) { continue; }
679  int phicellnew = phicell+ii;
680  // for test beam no phi wrapping
681  if (m_NCellTot != 1024 && ( phicellnew<0 || phicellnew >= m_NCellTot)) { continue; }
682  if (phicellnew < 0) { phicellnew += m_NCellTot; }
683  if (phicellnew >= m_NCellTot) { phicellnew -= m_NCellTot; }
684  double xln;
685  int nstr2=currentCellData.nstraight;
686  double dElec = Distance_Ele(xPosition,yPosition,phicellnew,nstr2,currentCellData.nfold,xln);
687  if (std::fabs(dElec)<std::fabs(dElecMin)) {
688  phicellmin=phicellnew;
689  xlmin=xln;
690  dElecMin = dElec;
691  nstr=nstr2;
692  }
693  }
694  currentCellData.phiGap = phicellmin;
695  currentCellData.distElec = dElecMin;
696  currentCellData.xl = xlmin;
697  currentCellData.nstraight = nstr;
698  } // end distance >2.5mm
699  else {
700  currentCellData.phiGap=phicell;
701  currentCellData.distElec=distElec;
702  currentCellData.xl=xl;
703  currentCellData.nstraight=nstr;
704  }
705 
706 #ifdef DEBUGHITS
707  ATH_MSG_VERBOSE(" final phiGap,distElec,xl " << currentCellData.phiGap << " " << currentCellData.distElec << " "
708  << currentCellData.xl);
709 #endif
710 
711  // compute distance to absorber
712 
713  G4int nabs;
714  if (currentCellData.distElec<0) nabs=currentCellData.phiGap;
715  else nabs=currentCellData.phiGap+1;
716  if (nabs >= m_NCellMax) nabs -= m_NCellMax;
717  currentCellData.distAbs = Distance_Abs(xPosition,yPosition,nabs,currentCellData.nstraight,currentCellData.nfold);
718 #ifdef DEBUGHITS
719  ATH_MSG_VERBOSE(" nabs,distAbs " << nabs << " " << currentCellData.distAbs);
720 #endif
721 
722  // in some rare cases near fold, the closest distance could give the wrong gap
723  // in such case, the signs of distAbs and distElec are not opposite as they should
724  if ((currentCellData.distAbs>0. && currentCellData.distElec>0) ||
725  (currentCellData.distAbs<0. && currentCellData.distElec<0) ) {
726  // ATH_MSG_VERBOSE("distElec and distAbs same sign " << currentCellData.distElec << " " << currentCellData.distAbs);
727  // ATH_MSG_VERBOSE(" currentCellData.phiGap " << currentCellData.phiGap);
728  if (std::fabs(currentCellData.distElec)>std::fabs(currentCellData.distAbs)) {
729  if (currentCellData.distAbs>0) { currentCellData.phiGap += 1; }
730  if (currentCellData.distAbs<0) { currentCellData.phiGap -= 1; }
731  if (m_NCellTot != 1024) {
732  if (currentCellData.phiGap <0) { currentCellData.phiGap=0; }
733  if (currentCellData.phiGap >= m_NCellTot) { currentCellData.phiGap = m_NCellTot-1; }
734  }
735  else {
736  if (currentCellData.phiGap < 0) { currentCellData.phiGap += m_NCellTot; }
737  if (currentCellData.phiGap >= m_NCellTot) { currentCellData.phiGap -= m_NCellTot; }
738  }
739  currentCellData.distElec = Distance_Ele(xPosition,yPosition,currentCellData.phiGap,currentCellData.nstraight,currentCellData.nfold,currentCellData.xl);
740  // ATH_MSG_VERBOSE(" new phiGap,distElec " << currentCellData.phiGap << " " << currentCellData.distElec);
741  }
742  }
743 
744  currentCellData.phiBin = (G4int) ( currentCellData.phiGap/sampling_phi_nGaps );
745 
746  if (MapDetail) {
747  // compute x0,y0 coordinates in local electrode frame, using closest fold
748  // as reference
749  const G4double alpha = m_coudeelec->PhiRot(currentCellData.nfold,currentCellData.phiGap);
750  const G4double dx=xPosition-m_coudeelec->XCentCoude(currentCellData.nfold,currentCellData.phiGap);
751  const G4double dy=yPosition-m_coudeelec->YCentCoude(currentCellData.nfold,currentCellData.phiGap);
752  const G4double dx1=dx*cos(alpha)-dy*sin(alpha);
753  const G4double dy1=dx*sin(alpha)+dy*cos(alpha);
754  currentCellData.x0 = dx1 + m_xc[currentCellData.nfold];
755  currentCellData.y0 = dy1 + m_yc[currentCellData.nfold];
756  if (m_parity==1) { currentCellData.y0 = -1*currentCellData.y0; }
757  }
758 
759 
760  } // end of findCell method
761 
762  // =============================================================================
763  // initialize phi0 vs radius of first absorber (for gam=0)
764  void Geometry::GetRphi()
765  {
766  const G4double dl=0.001;
767  const G4double inv_dl = 1. / dl;
768  G4double cenx[15],ceny[15];
769  //G4double xl,xl2;
770  std::vector<G4double> sum1(5000);
771  std::vector<G4double> sumx(5000);
772  //xl=0;
773  //xl2=0.;
774  m_NRphi=5000;
775  m_Rmin=1500.;
776  m_dR=0.10;
777  m_Rmax=0.;
778 
779  const G4double rint= m_rint_eleFib;
780  const G4double inv_rint = 1. / rint;
781  const G4double dt=dl * inv_rint;
782  const G4double inv_dt = 1. / dt;
783 
784  for (G4int i=0;i<m_NRphi;i++) {
785  sum1[i]=0.;
786  sumx[i]=0.;
787  }
788  for (G4int i=0;i<15;i++) {
789  cenx[i]=m_rc[i]*cos(m_phic[i]);
790  ceny[i]=m_rc[i]*sin(m_phic[i]);
791  }
792 
793  for (G4int i=0; i<15; i++) {
794 
795  // fold
796  G4double phi0,phi1;
797  if (i==0) {
798  // first fold goes up
799  if (m_parity==0) {
800  phi0=-CLHEP::pi/2.;
801  phi1=-m_delta[0];
802  }
803  // first fold goes down
804  else {
805  phi0=m_delta[0];
806  phi1=CLHEP::pi/2;
807  }
808  }
809  else if (i==14) {
810  if (m_parity==0) {
811  phi0=-CLHEP::pi+m_delta[13];
812  phi1=-CLHEP::pi/2.;
813  }
814  else {
815  phi0=CLHEP::pi/2;
816  phi1=CLHEP::pi - m_delta[13];
817  }
818  }
819  else {
820  if (i%2==(1-m_parity)) {
821  phi0=m_delta[i];
822  phi1=CLHEP::pi-m_delta[i-1];
823  }
824  else {
825  phi0=-CLHEP::pi+m_delta[i-1];
826  phi1=-m_delta[i];
827  }
828  }
829  //xl2+=rint*std::fabs(phi1-phi0);
830  const G4int nstep=int((phi1-phi0)*inv_dt)+1;
831  for (int ii=0;ii<nstep;ii++) {
832  //xl+=dl;
833  const G4double phi=phi0+dt*((G4double)ii);
834  const G4double x=cenx[i]+rint*cos(phi);
835  const G4double y=ceny[i]+rint*sin(phi);
836  const G4double radius=sqrt(x*x+y*y);
837  if (radius>m_Rmax) { m_Rmax=radius; }
838  const G4double phid=atan(y/x);
839  const G4int ir=((int) ((radius-m_Rmin)/m_dR) );
840  if (ir>=0 && ir < m_NRphi) {
841  sum1[ir]+=1.;
842  sumx[ir]+=phid;
843  }
844  }
845 
846  // straight section
847  if (i<14) {
848  const G4double dx=cenx[i+1]-cenx[i];
849  const G4double dy=ceny[i+1]-ceny[i];
850  const G4double along=std::sqrt(dx*dx+dy*dy-4.*rint*rint);
851  const G4double x0=0.5*(cenx[i+1]+cenx[i]);
852  const G4double y0=0.5*(ceny[i+1]+ceny[i]);
853  const G4double phi = (i%2==m_parity) ? CLHEP::pi/2-m_delta[i] : -CLHEP::pi/2.+m_delta[i];
854  const G4double x1=x0-0.5*along*cos(phi);
855  const G4double y1=y0-0.5*along*sin(phi);
856  //xl2+=along;
857  const int nstep=int(along*inv_dl)+1;
858  for (int ii=0;ii<nstep;ii++) {
859  //xl+=dl;
860  const G4double x=x1+dl*((G4double)ii)*cos(phi);
861  const G4double y=y1+dl*((G4double)ii)*sin(phi);
862  const G4double radius=sqrt(x*x+y*y);
863  if (radius>m_Rmax) { m_Rmax=radius; }
864  const G4double phid=atan(y/x);
865  const G4int ir=((int) ((radius-m_Rmin)/m_dR) );
866  if (ir>=0 && ir < m_NRphi) {
867  sum1[ir]+=1.;
868  sumx[ir]+=phid;
869  }
870  }
871  }
872  }
873  // ATH_MSG_VERBOSE("total electrode length " << xl << " " << xl2);
874  // ATH_MSG_VERBOSE("rmax in accordion " << m_Rmax);
875  for (int i=0; i<m_NRphi; i++) {
876  if (sum1[i]>0) {
877  m_Rphi[i]=sumx[i]/sum1[i];
878  // Not used:
879  //G4double radius = m_Rmin + ((G4double(i))+0.5)*m_dR;
880  //ATH_MSG_VERBOSE(" GUTEST r,phi0 " << radius << " " << m_Rphi[i]);
881  }
882  else { m_Rphi[i]=0.; }
883  }
884  }
885 
886  // ======================================================================================
887  // phi of first absorber as function of radius for nominal accordion geometry
888  // (before sagging)
889  G4double Geometry::Phi0(G4double radius) const
890  {
891  // TODO This function could be simplified.
892  G4int ir;
893  if (radius < m_Rmin) { ir=0; }
894  else {
895  if (radius > m_Rmax) radius=m_Rmax-0.0001;
896  ir=((int) ((radius-m_Rmin)/m_dR) );
897  }
898  return m_Rphi[ir];
899  }
900 
901  // ======================================================================================
902  // compute number (0 to 1023) of closest electrode according to nominal
903  // accordion geometry
904  G4int Geometry::PhiGap(const double & radius, const double & xhit, const double &yhit) const
905  {
906  const G4double phi0=Phi0(radius)+m_gam0; // from -pi to pi
907  const G4double phi_hit=atan2(yhit,xhit); // from -pi to pi
908  G4double dphi=phi_hit-phi0;
909  // bring back to 0-2pi
910  if (dphi<0) dphi=dphi+2*M_PI;
911  if (dphi>=2*M_PI) dphi=dphi-2*M_PI;
912  dphi=dphi/(2*M_PI)*1024;
913  const G4int ngap=((int) dphi);
914 #ifdef DEBUGHITS
915  ATH_MSG_VERBOSE(" phi0 " << phi0 << " dphi, ngap " << dphi << " " << ngap);
916 #endif
917  return ngap;
918  }
919 
920  //===================================================================================
921  // full cell id computation starting from an arbitrary G4 step
922 
923  LArG4Identifier Geometry::CalculateIdentifier(const G4Step* a_step) const
924  {
925 
926  // The default result is a blank identifier.
928 
929  // Get all the required information from the current step
930  const G4NavigationHistory* g4navigation = a_step->GetPreStepPoint()->GetTouchable()->GetHistory();
931  const G4int ndep = g4navigation->GetDepth();
932  bool inSTAC = false;
933  int zside=1;
934  G4int indECAM = -999;
935 
936  // Now navigate through the volumes hierarchy
937  for (G4int ii=0;ii<=ndep;ii++) {
938  const G4String& vname = g4navigation->GetVolume(ii)->GetName();
939  // FIXME Need to find a way to avoid these string-comparisons
940  if ( indECAM<0 && vname == m_ecamName ) indECAM=ii;
941  if ( !inSTAC && vname.find("STAC") !=std::string::npos) inSTAC=true;
942  if ( vname.find("NegPhysical") != std::string::npos) zside=-1;
943  }
944  if (indECAM>=0)
945  result = this->CalculateECAMIdentifier( a_step , indECAM, inSTAC, zside) ;
946  else
947  ATH_MSG_ERROR("LArBarrel::Geometry::CalculateIdentifier ECAM volume not found in hierarchy");
948 
949  return result;
950  }
951 
952  //======================================================================================
953  //
954  // The following method computes the identifiers in the ECAM volume:
955  // (including dead material identifier)
956  //
957  // 1) Tranformation into LOCAL half barrel frame
958  //
959  // 2) Check if the hit is in the fiducial region (EM accordion, no presampler)
960  // fiducial range: 1500.24 < r < 1960.00 mm
961  // |eta| < 1.475
962  // 4 < z < 3164 mm (in local half barrel coordinates)
963  //
964  // 3) If the hit is in the fiducial region standard identifier are filled
965  //
966  // 4) If the hit is outside the fiduacial region calibration hits are filled
967  //
968  // CaloDM_ID identifier for the barrel:
969  //
970  // detector_system/subdet/type/sampling/region/eta/phi
971  //
972  // * For hits with radius < 1500.24
973  // ******************************
974  //
975  // detector system = 10 -> Calorimeters
976  // subdet = +/-4 -> LAr dead materials
977  // type = 1 -> dead materials outside accordion and active presampler layers
978  // sampling = 1 -> dead materials in front and in active LAr calorimeters (starting from front warm
979  // cryostat walls)
980  // regions: = 3 -> all materials from the active layer of the barrel presampler to the active layer
981  // of accordion, 0 < |eta| < 1.5
982  //
983  // ---> Granularity : deta 0.1 granularity within region
984  // dphi pi/32 ~ 0.1 granularity within region
985  //
986  // * For hits with radius > 1960.00
987  // ******************************
988  //
989  // detector system = 10 -> Calorimeters
990  // subdet = +/-4 -> LAr dead materials
991  // type = 1 -> dead materials outside accordion and active presampler layers
992  // sampling = 2 -> dead materials between active LAr calorimeters and Tile calorimeters or HEC-2 wheels
993  // regions: = 0 -> all materials behind the active layer of accordion in front the Tile barrel
994  // for |eta| < 1.0
995  // =2 -> all materials in front of the scintillator and behind the active layer of accordion
996  // for 1.0 < |eta| < 1.5
997  //
998  // ---> Granularity : deta 0.1 granularity within region
999  // dphi pi/32 ~ 0.1 granularity within region
1000  //
1001  //======================================================================================
1002 
1003  LArG4Identifier Geometry::CalculateECAMIdentifier(const G4Step* a_step, const G4int indECAM, const bool inSTAC, int zside) const
1004  {
1005 
1007 
1008  // Get all the information about the step
1009 
1010  const G4StepPoint *thisStepPoint = a_step->GetPreStepPoint();
1011  const G4StepPoint *thisStepBackPoint = a_step->GetPostStepPoint();
1012  const G4ThreeVector startPoint = thisStepPoint->GetPosition();
1013  const G4ThreeVector endPoint = thisStepBackPoint->GetPosition();
1014  const G4ThreeVector p = (thisStepPoint->GetPosition() + thisStepBackPoint->GetPosition()) * 0.5;
1015 
1016 #ifdef DEBUGHITS
1017  ATH_MSG_VERBOSE("Position of the step in the ATLAS frame (x,y,z) --> " << p.x() << " " << p.y() << " " << p.z());
1018  ATH_MSG_VERBOSE("Eta and Phi in the ATLAS frame --> " << p.eta() << " " << p.phi());
1019 #endif
1020 
1021  // BACK directly into the LOCAL half_Barrel. All the variables in this LOCAL framework get the SUFFIX Zpos
1022 
1023  const G4NavigationHistory* g4navigation = thisStepPoint->GetTouchable()->GetHistory();
1024  const G4AffineTransform transformation = g4navigation->GetTransform(indECAM);
1025  const G4ThreeVector startPointinLocal = transformation.TransformPoint(startPoint);
1026  const G4ThreeVector endPointinLocal = transformation.TransformPoint (endPoint);
1027  const G4ThreeVector midinLocal = (startPointinLocal+endPointinLocal)*0.5;
1028 
1029 #ifdef DEBUGHITS
1030  ATH_MSG_VERBOSE("Position of the step in the LOCAL frame (x,y,z) --> " << midinLocal.x() << " " << midinLocal.y() << " " << midinLocal.z());
1031  ATH_MSG_VERBOSE("Eta and Phi of the step in LOCAL frame --> " << midinLocal.eta() << " " << midinLocal.phi());
1032 #endif
1033 
1034  // coordinates in the local frame
1036  const G4double xZpos = midinLocal.x();
1037  const G4double yZpos = midinLocal.y();
1038  const G4double zZpos = midinLocal.z();
1039  const G4double etaZpos = midinLocal.pseudoRapidity();
1040  const G4double phiZpos = (midinLocal.phi()<0.) ? midinLocal.phi() + 2.*M_PI : midinLocal.phi();
1041  const G4double radius2Zpos = xZpos*xZpos + yZpos*yZpos;
1042  const G4double radiusZpos = sqrt(radius2Zpos);
1043 
1044  CalcData currentCellData;
1045  if (m_testbeam) {
1046  currentCellData.zSide = 1;
1047  }
1048  else {
1049  currentCellData.zSide = zside;
1050  }
1051 
1052  // Check if the hit is in the fiducial range and in the STAC volume
1053  // if yes this is active or inactive material
1054 
1055  if (inSTAC && radiusZpos >=m_rMinAccordion && radiusZpos <= m_rMaxAccordion &&
1056  zZpos <= m_zMaxBarrel && zZpos >= m_zMinBarrel && etaZpos <= m_etaMaxBarrel) {
1057 
1058 #ifdef DEBUGHITS
1059  ATH_MSG_VERBOSE("This hit is in the STAC volume !!!!! ");
1060 #endif
1061 
1062  // DETERMINATION of currentCellData.cellID,
1063  // currentCellData.zSide, currentCellData.sampling,
1064  // currentCellData.phiBin, currentCellData.etaBin,
1065  // m_stackNumID
1066  const bool MapDetail(false);
1067  this->findCell( currentCellData, xZpos, yZpos, zZpos, radiusZpos, etaZpos, phiZpos, MapDetail );
1068 
1069  // adjust phi in the negative half barrel frame
1070 
1071  if( currentCellData.zSide == -1 )
1072  {
1073  if( currentCellData.sampling == 1 && currentCellData.region ==0 )
1074  {
1075  currentCellData.phiBin = 31 - currentCellData.phiBin;
1076  if(currentCellData.phiBin < 0 ) currentCellData.phiBin += 64;
1077  }
1078  if( currentCellData.sampling == 1 && currentCellData.region ==1 )
1079  {
1080  currentCellData.phiBin = 127 - currentCellData.phiBin;
1081  if(currentCellData.phiBin < 0 ) currentCellData.phiBin += 256;
1082  }
1083  if( currentCellData.sampling >= 2 )
1084  {
1085  currentCellData.phiBin = 127 - currentCellData.phiBin;
1086  if(currentCellData.phiBin < 0 ) currentCellData.phiBin += 256;
1087  }
1088  }
1089 
1090  // there are few hundred microns between the 4mm nominal beginning of the active region
1091  // and the real beginning of the first strip at eta=0.025/8
1092  // to avoid inactive energy with strip=0 assign this to strip=1
1093  if (currentCellData.sampling==1 && currentCellData.region==0 && currentCellData.etaBin==0) {
1094  currentCellData.etaBin=1;
1095  }
1096 
1097  result << 4 // LArCalorimeter
1098  << 1 // LArEM
1099  << currentCellData.zSide
1100  << currentCellData.sampling
1101  << currentCellData.region
1102  << currentCellData.etaBin
1103  << currentCellData.phiBin;
1104 
1105 #ifdef DEBUGHITS
1106  ATH_MSG_VERBOSE("Here the identifier for the barrel ACTIVE ----> ");
1107  ATH_MSG_VERBOSE("eta in local frame --> " << etaZpos);
1108  ATH_MSG_VERBOSE("currentCellData.zSide ----> " << currentCellData.zSide);
1109  ATH_MSG_VERBOSE("currentCellData.sampling ----> " << currentCellData.sampling);
1110  ATH_MSG_VERBOSE("currentCellData.region ----> " << currentCellData.region);
1111  ATH_MSG_VERBOSE("currentCellData.etaBin ----> " << currentCellData.etaBin);
1112  ATH_MSG_VERBOSE("currentCellData.phiBin ----> " << currentCellData.phiBin);
1113  ATH_MSG_VERBOSE("And also etafirst ----> " << thisStepPoint->GetPosition().pseudoRapidity());
1114 #endif
1115 
1116  // if (!Geometry::CheckLArIdentifier(currentCellData.sampling,currentCellData.region,currentCellData.etaBin,currentCellData.phiBin)) {
1117  // ATH_MSG_ERROR(" ** Bad LAr identifier " << currentCellData.sampling << " " << currentCellData.region << " "
1118  // << currentCellData.etaBin << " " << currentCellData.phiBin);
1119  // ATH_MSG_ERROR(" x,y,z,eta,phi " << xZpos << " " << yZpos << " " << zZpos
1120  // << " " << radiusZpos << " " << etaZpos << " " << phiZpos);
1121  // }
1122 
1123 
1124  }
1125  // hits in dead material part
1126  else {
1127 
1128  G4int sampling=0;
1129  G4int region=0;
1130  const G4int numDeadPhiBins = 64;
1131  double abs_eta = std::fabs(etaZpos);
1132  const double DM1EtaWidth = 0.1 ;
1133  const double DM1PhiWidth = 2.*M_PI / numDeadPhiBins ;
1134  currentCellData.etaBin = (G4int) ( abs_eta * (1./DM1EtaWidth) ) ;
1135  currentCellData.phiBin = (G4int) (phiZpos/ DM1PhiWidth );
1136  G4int type=1;
1137  // protect against rounding error for phi ~2pi
1138  if (currentCellData.phiBin==numDeadPhiBins) currentCellData.phiBin=currentCellData.phiBin-1;
1139 
1140  // adjust phi for negative half barrel
1141 
1142  if ( currentCellData.zSide == -1 ) {
1143  currentCellData.phiBin = 31 - currentCellData.phiBin;
1144  if (currentCellData.phiBin < 0 ) currentCellData.phiBin +=64 ;
1145  }
1146 
1147  // material in front of the active accordion
1148  if ( radiusZpos < m_rMinAccordion ) {
1149  sampling =1 ;
1150  region = 3 ;
1151  if (currentCellData.etaBin > 14) currentCellData.etaBin=14;
1152 
1153 #ifdef DEBUGHITS
1154  ATH_MSG_VERBOSE("This hit is in the ECAM volume in front of the accordion (DEAD MATERIAL) !!!!! ");
1155 #endif
1156 
1157  } else if (radiusZpos >= m_rMaxAccordion){ // material behind the active accordion
1158  sampling = 2;
1159 
1160  if (abs_eta < 1.0 ) {
1161  region = 0 ;
1162 #ifdef DEBUGHITS
1163  ATH_MSG_VERBOSE("This hit is in the ECAM volume behind accordion (DEAD MATERIAL 0) !!!!! ");
1164 #endif
1165  } else if ( abs_eta >= 1.0 && abs_eta < 1.5) {
1166  region = 2;
1167  currentCellData.etaBin = currentCellData.etaBin - 10; // to have etabin between 0 and 4
1168 #ifdef DEBUGHITS
1169  ATH_MSG_VERBOSE("This hit is in the ECAM volume behind accordion (DEAD MATERIAL 2) !!!!! ");
1170 #endif
1171  } else {
1172  ATH_MSG_ERROR(" LArBarrelGeometry: hit behind accordion at eta>1.5 !!! ");
1173  region = 2;
1174  currentCellData.etaBin = 4;
1175  }
1176 
1177  } else if (zZpos <= m_zMinBarrel) { // inactive matter between two EMB halves
1178  type=2;
1179  region=0;
1180  const G4int phisave=currentCellData.phiBin;
1181  const G4bool MapDetail(false);
1182  this->findCell( currentCellData, xZpos, yZpos, zZpos, radiusZpos, etaZpos, phiZpos, MapDetail );
1183  sampling = currentCellData.sampling; // sampling as in normal definition
1184  currentCellData.etaBin=0;
1185  currentCellData.phiBin=phisave;
1186 
1187  } else if (zZpos >= m_zMaxBarrel - m_zMaxBarrelDMMargin || abs_eta >= 1.40) { // inactive matter between EMB and scintillator including some margin for error
1188  if (abs_eta >1.0 && abs_eta < 1.5) {
1189  sampling=2;
1190  region=2;
1191  currentCellData.etaBin = currentCellData.etaBin - 10; // to have etabin between 0 and 4
1192  } else if (abs_eta < 1.6) {
1193  sampling=1;
1194  region=4;
1195  currentCellData.etaBin=0;
1196  } else {
1197  ATH_MSG_ERROR(" LArBarrelGeometry: hit at eta>1.6 !!! ");
1198  sampling=1;
1199  region=4;
1200  currentCellData.etaBin=0;
1201  }
1202  } else {
1203  if (!m_testbeam) {
1204  const G4double thisStepEnergyDeposit = a_step->GetTotalEnergyDeposit() * a_step->GetTrack()->GetWeight();
1205  std::ostringstream dmLog;
1206  dmLog << "LArBarrelGeometry: cannot find region for DM hit..." << std::endl;
1207  dmLog << "LArBarrelGeometry: cannot find region for DM hit..." << std::endl;
1208  dmLog << "m_zMinBarrel: " << m_zMinBarrel << std::endl;
1209  dmLog << "m_zMaxBarrel: " << m_zMaxBarrel << std::endl;
1210  dmLog << "m_rMinAccordion: " << m_rMinAccordion << std::endl;
1211  dmLog << "m_rMaxAccordion: " << m_rMaxAccordion << std::endl;
1212  dmLog << "r,z,eta,phi " << radiusZpos << " " << zZpos << " " << etaZpos << " " << phiZpos << std::endl;
1213  dmLog << "x,y,z (Atlas) " << p.x() << " " << p.y() << " " << p.z() << std::endl;
1214  dmLog << " inSTAC " << inSTAC << std::endl;
1215  dmLog << " eDeposited " << thisStepEnergyDeposit << std::endl;
1216  const G4VPhysicalVolume* vol = thisStepPoint->GetPhysicalVolume();
1217  const G4String volName = vol->GetName();
1218  dmLog << " volName " << volName << std::endl;
1219  const G4int ndep = g4navigation->GetDepth();
1220  for (G4int ii=0;ii<=ndep;ii++) {
1221  const G4VPhysicalVolume* v1 = g4navigation->GetVolume(ii);
1222  const G4String vname = v1->GetName();
1223  dmLog << "vname " << vname << std::endl;
1224  }
1225  if (thisStepEnergyDeposit > 1.*CLHEP::MeV) {
1226  ATH_MSG_ERROR(dmLog.str());
1227  } else {
1228  ATH_MSG_WARNING(dmLog.str());
1229  }
1230  }
1231  // in test beam case, we can get there for leakage on the side (in phi) of the module
1232  // in this case, we attribute an identifier like inactive material
1233  else
1234  {
1235  G4bool MapDetail=false;
1236  this->findCell( currentCellData, xZpos, yZpos, zZpos, radiusZpos, etaZpos, phiZpos, MapDetail );
1237  // ATH_MSG_ERROR(" Lateral lakage r,eta,phi " << radiusZpos << " " << etaZpos << " "
1238  // << phiZpos << " sampling/region/eta/phi " << currentCellData.sampling << " " <<
1239  // currentCellData.region << " " << currentCellData.etaBin << " " << currentCellData.phiBin);
1240  // protect against small space between z=4m and real beginning of ieta=1 in strips
1241  if (currentCellData.sampling==1 && currentCellData.region==0 && currentCellData.etaBin==0) {
1242  currentCellData.etaBin=1;
1243  // ATH_MSG_ERROR("S1R0 etabin 0 found r,z,phi local " << radiusZpos << " "
1244  // << " " << zZpos << " " << phiZpos);
1245  }
1246  result << 4 // LArCalorimeter
1247  << 1 // LArEM
1248  << currentCellData.zSide
1249  << currentCellData.sampling
1250  << currentCellData.region
1251  << currentCellData.etaBin
1252  << currentCellData.phiBin;
1253  return result;
1254  }
1255  }
1256 
1257  result << 10 // LArCalorimeter
1258  << currentCellData.zSide * 4 // LArBarrel
1259  << type
1260  << sampling
1261  << region
1262  << currentCellData.etaBin
1263  << currentCellData.phiBin;
1264 
1265 #ifdef DEBUGHITS
1266  ATH_MSG_VERBOSE("Here the identifier for the barrel DEAD materials ---->");
1267  ATH_MSG_VERBOSE("Type ----> " << type);
1268  ATH_MSG_VERBOSE("Sampling ----> " << sampling);
1269  ATH_MSG_VERBOSE("Region ----> " << region);
1270  ATH_MSG_VERBOSE("zSide ----> " << currentCellData.zSide*4);
1271  ATH_MSG_VERBOSE("etaBin ----> " << currentCellData.etaBin);
1272  ATH_MSG_VERBOSE("phiBin ----> " << currentCellData.phiBin);
1273 #endif
1274 
1275  // if (!Geometry::CheckDMIdentifier(type,sampling,region,currentCellData.etaBin,currentCellData.phiBin)) {
1276  // ATH_MSG_ERROR(" ** Bad DM identifier " << type << " " << sampling << " " << region << " "
1277  // << currentCellData.etaBin << " " << currentCellData.phiBin);
1278  // ATH_MSG_ERROR("x,y,z,r,eta,phi" << xZpos << " " << yZpos << " " << zZpos <<
1279  // " " << radiusZpos << " " << etaZpos << " " << phiZpos);
1280  // }
1281 
1282  }
1283 
1284  return result;
1285 
1286  }
1287 
1288  bool Geometry::CheckDMIdentifier(int type, int sampling, int region, int eta, int phi) const
1289  {
1290 
1291  if (type <1 || type > 2) return false;
1292  if (type==1) {
1293  if (sampling<1 || sampling>2) return false;
1294  if (sampling==1) {
1295  if (region!=3 && region !=4) return false;
1296  if (phi<0 || phi>63) return false;
1297  if (region==3) {
1298  if (eta<0 || eta>14) return false;
1299  }
1300  if (region==4) {
1301  if (eta !=0) return false;
1302  }
1303  }
1304  if (sampling==2) {
1305  if (region !=0 && region !=2) return false;
1306  if (phi<0 || phi>63) return false;
1307  if (region==0){
1308  if (eta<0 || eta>9) return false;
1309  }
1310  if (region==2) {
1311  if (eta<0 || eta>4) return false;
1312  }
1313  }
1314  }
1315  if (type==2) {
1316  if (sampling<1 || sampling >3) return false;
1317  if (region !=0) return false;
1318  if (eta!=0) return false;
1319  if (phi<0 || phi>63) return false;
1320  }
1321  return true;
1322  }
1323 
1324 
1325  bool Geometry::CheckLArIdentifier(int sampling, int region, int eta, int phi) const
1326  {
1327  if (sampling<0 || sampling >3) return false;
1328  if (sampling==0) {
1329  if (region!=0) return false;
1330  if (eta<0 || eta>60) return false;
1331  if (phi<0 || phi>63) return false;
1332  }
1333  if (sampling==1) {
1334  if (region<0 || region >1) return false;
1335  if (region==0) {
1336  if (eta<1 || eta>447) return false;
1337  if (phi<0 || phi>63) return false;
1338  }
1339  if (region==1) {
1340  if (eta<0 || eta>2) return false;
1341  if (phi<0 || phi>255) return false;
1342  }
1343  }
1344  if (sampling==2) {
1345  if (region<0 || region >1) return false;
1346  if (region==0) {
1347  if (eta<0 || eta>55) return false;
1348  if (phi<0 || phi>255) return false;
1349  }
1350  if (region==1) {
1351  if (eta!=0) return false;
1352  if (phi<0 || phi>255) return false;
1353  }
1354  }
1355  if (sampling==3) {
1356  if (region !=0) return false;
1357  if (eta<0 || eta>26) return false;
1358  if (phi<0 || phi>255) return false;
1359  }
1360  return true;
1361  }
1362 
1363  } //end of Barrel namespace
1364 
1365 } // end of LArG4 namespace
LArG4::Barrel::Geometry::PhiGap
G4int PhiGap(const double &, const double &, const double &) const
Definition: LArBarrelGeometry.cxx:936
LArBarrelSampling.h
plotBeamSpotCompare.x1
x1
Definition: plotBeamSpotCompare.py:215
LArStraightAbsorbers::Sinu
double Sinu(int stackid, int cellid) const
Definition: LArStraightAbsorbers.h:29
LArG4::Barrel::Geometry::m_parity
int m_parity
Definition: LArBarrelGeometry.h:96
LArG4Identifier
Definition: LArG4Identifier.h:121
LArStraightAbsorbers::GetInstance
static const LArStraightAbsorbers * GetInstance(const std::string &strDetector="")
Definition: LArStraightAbsorbers.cxx:11
LArG4::Barrel::Geometry::m_Rmax
G4double m_Rmax
Definition: LArBarrelGeometry.h:109
LArCoudeElectrodes::XCentCoude
double XCentCoude(int stackid, int cellid) const
Definition: LArCoudeElectrodes.h:19
TestSUSYToolsAlg.dl
dl
Definition: TestSUSYToolsAlg.py:81
LArStraightAbsorbers::XCentAbs
double XCentAbs(int stackid, int cellid) const
Definition: LArStraightAbsorbers.h:25
add-xsec-uncert-quadrature-N.alpha
alpha
Definition: add-xsec-uncert-quadrature-N.py:110
get_generator_info.result
result
Definition: get_generator_info.py:21
LArG4::Barrel::Geometry::m_Rphi
G4double m_Rphi[5000]
Definition: LArBarrelGeometry.h:110
LArStraightAbsorbers::YCentAbs
double YCentAbs(int stackid, int cellid) const
Definition: LArStraightAbsorbers.h:26
phi
Scalar phi() const
phi method
Definition: AmgMatrixBasePlugin.h:67
LArGeo::VDetectorParameters
Definition: VDetectorParameters.h:29
LArG4::Barrel::Geometry::m_Rmin
G4double m_Rmin
Definition: LArBarrelGeometry.h:108
LArG4::Barrel::Geometry::initializeForSDCreation
virtual void initializeForSDCreation() override final
Definition: LArBarrelGeometry.cxx:145
LArG4::Barrel::Geometry::m_NCellTot
int m_NCellTot
Definition: LArBarrelGeometry.h:80
eta
Scalar eta() const
pseudorapidity method
Definition: AmgMatrixBasePlugin.h:83
LArG4::Barrel::Geometry::m_phic
double * m_phic
Definition: LArBarrelGeometry.h:92
LArCoudeAbsorbers::XCentCoude
double XCentCoude(int stackid, int cellid) const
Definition: LArCoudeAbsorbers.h:19
LArG4::Barrel::Geometry::m_zMinBarrel
double m_zMinBarrel
Definition: LArBarrelGeometry.h:74
LArG4::Barrel::Geometry::Phi0
G4double Phi0(G4double) const
Definition: LArBarrelGeometry.cxx:921
LArG4::Barrel::Geometry::m_Nbrt
int m_Nbrt
Definition: LArBarrelGeometry.h:84
InDetAccessor::phi0
@ phi0
Definition: InDetAccessor.h:33
LArG4::Barrel::Geometry::Distance_Ele
double Distance_Ele(const double &x, const double &y, const int &PhiC, int &Num_Straight, const int &Num_Coude, double &xl) const
Definition: LArBarrelGeometry.cxx:185
LArBarrelGeometry.h
LArCoudeElectrodes::GetInstance
static const LArCoudeElectrodes * GetInstance(const std::string &strDetector="")
Definition: LArCoudeElectrodes.cxx:9
LArG4::Barrel::Geometry::m_rc
double * m_rc
Definition: LArBarrelGeometry.h:91
LArCoudeAbsorbers.h
M_PI
#define M_PI
Definition: ActiveFraction.h:11
LArStraightElectrodes::Sinu
double Sinu(int stackid, int cellid) const
Definition: LArStraightElectrodes.h:30
LArG4::Barrel::Geometry::m_coudeelec
const LArCoudeElectrodes * m_coudeelec
Definition: LArBarrelGeometry.h:99
LArG4::Barrel::Geometry::m_electrode
const LArStraightElectrodes * m_electrode
Definition: LArBarrelGeometry.h:101
LArG4::Barrel::CalcData
Definition: ILArBarrelGeometry.h:26
python.TurnDataReader.dr
dr
Definition: TurnDataReader.py:111
drawFromPickle.cos
cos
Definition: drawFromPickle.py:36
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
LArG4::Barrel::Geometry::Geometry
Geometry()
LArG4::Barrel::Geometry::m_etaMaxBarrel
double m_etaMaxBarrel
Definition: LArBarrelGeometry.h:77
LArG4::Barrel::Geometry::m_testbeam
Gaudi::Property< bool > m_testbeam
Definition: LArBarrelGeometry.h:67
x
#define x
LArG4::Barrel::Geometry::findCell
virtual void findCell(CalcData &currentCellData, const double &x, const double &y, const double &z, const double &r, const double &eta, const double &phi, const bool detail) const override final
Definition: LArBarrelGeometry.cxx:612
LArG4
Definition: LArWheelCalculatorEnums.h:8
LArStraightElectrodes::Cosu
double Cosu(int stackid, int cellid) const
Definition: LArStraightElectrodes.h:29
Trk::u
@ u
Enums for curvilinear frames.
Definition: ParamDefs.h:77
python.CaloAddPedShiftConfig.type
type
Definition: CaloAddPedShiftConfig.py:42
makeTRTBarrelCans.y1
tuple y1
Definition: makeTRTBarrelCans.py:15
pi
#define pi
Definition: TileMuonFitter.cxx:65
drawFromPickle.atan
atan
Definition: drawFromPickle.py:36
LArG4::Barrel::Geometry::SampSeg
G4int SampSeg(G4double, G4double, G4double, G4int &, G4int &, G4int &, G4int &, G4int &) const
Definition: LArBarrelGeometry.cxx:326
DetType::Barrel
@ Barrel
Definition: DetType.h:14
python.SystemOfUnits.MeV
float MeV
Definition: SystemOfUnits.py:172
LArCoudeElectrodes::PhiRot
double PhiRot(int stackid, int cellid) const
Definition: LArCoudeElectrodes.h:21
LArG4::Barrel::Geometry::CalculateECAMIdentifier
LArG4Identifier CalculateECAMIdentifier(const G4Step *, const G4int indEcam, const bool inSTAC=true, int zside=1) const
Definition: LArBarrelGeometry.cxx:1035
LArG4::Barrel::Geometry::GetRphi
void GetRphi()
phi vs r of first absorber in nominal geometry
Definition: LArBarrelGeometry.cxx:796
LArG4::Barrel::Geometry::m_ecamName
G4String m_ecamName
Definition: LArBarrelGeometry.h:69
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:209
LArG4::Barrel::Geometry::CheckDMIdentifier
bool CheckDMIdentifier(int type, int sampling, int region, int eta, int phi) const
Definition: LArBarrelGeometry.cxx:1320
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
LArG4::Barrel::Geometry::CalculateIdentifier
virtual LArG4Identifier CalculateIdentifier(const G4Step *) const override final
Definition: LArBarrelGeometry.cxx:955
LArG4::Barrel::Geometry::finalize
virtual StatusCode finalize() override final
Definition: LArBarrelGeometry.cxx:156
LArStraightElectrodes::XCentEle
double XCentEle(int stackid, int cellid) const
Definition: LArStraightElectrodes.h:26
lumiFormat.i
int i
Definition: lumiFormat.py:85
z
#define z
LArG4::Barrel::Geometry::m_rint_eleFib
double m_rint_eleFib
Definition: LArBarrelGeometry.h:89
python.CaloCondTools.g
g
Definition: CaloCondTools.py:15
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
CaloNoise_fillDB.dt
dt
Definition: CaloNoise_fillDB.py:56
LArG4::Barrel::Geometry::Distance_Abs
double Distance_Abs(const double &x, const double &y, const int &nabs, const int &Num_Straight, const int &Num_Coude) const
Definition: LArBarrelGeometry.cxx:259
LArG4::Barrel::Geometry::m_gam0
double m_gam0
Definition: LArBarrelGeometry.h:88
LArG4::Barrel::CalcData::phiBin
G4int phiBin
Definition: ILArBarrelGeometry.h:31
LArStraightElectrodes.h
LArG4::Barrel::Geometry::initialize
virtual StatusCode initialize() override final
Definition: LArBarrelGeometry.cxx:82
PixelAthClusterMonAlgCfg.zmax
zmax
Definition: PixelAthClusterMonAlgCfg.py:169
LArG4::Barrel::Geometry::m_absorber
const LArStraightAbsorbers * m_absorber
Definition: LArBarrelGeometry.h:102
LArCoudeElectrodes::YCentCoude
double YCentCoude(int stackid, int cellid) const
Definition: LArCoudeElectrodes.h:20
LArStraightAbsorbers::HalfLength
double HalfLength(int stackid, int cellid) const
Definition: LArStraightAbsorbers.h:27
xAOD::double
double
Definition: CompositeParticle_v1.cxx:159
LArG4::Barrel::Geometry::m_Nbrt1
int m_Nbrt1
Definition: LArBarrelGeometry.h:85
LArG4::Barrel::CalcData::region
G4int region
Definition: ILArBarrelGeometry.h:29
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
LArCoudeElectrodes.h
LArG4::Barrel::Geometry::m_dR
G4double m_dR
Definition: LArBarrelGeometry.h:111
LArCoudeAbsorbers::GetInstance
static const LArCoudeAbsorbers * GetInstance(const std::string &strDetector="")
Definition: LArCoudeAbsorbers.cxx:9
LArG4::Barrel::CalcData::zSide
G4int zSide
Definition: ILArBarrelGeometry.h:32
LArG4::Barrel::Geometry::m_yc
double * m_yc
Definition: LArBarrelGeometry.h:94
ParticleGun_SamplingFraction.radius
radius
Definition: ParticleGun_SamplingFraction.py:96
LArG4::Barrel::Geometry::m_coudeabs
const LArCoudeAbsorbers * m_coudeabs
Definition: LArBarrelGeometry.h:100
LArG4::Barrel::Geometry::CheckLArIdentifier
bool CheckLArIdentifier(int sampling, int region, int eta, int phi) const
Definition: LArBarrelGeometry.cxx:1357
LArG4::Barrel::CalcData::etaBin
G4int etaBin
Definition: ILArBarrelGeometry.h:30
LArStraightElectrodes::YCentEle
double YCentEle(int stackid, int cellid) const
Definition: LArStraightElectrodes.h:27
ir
int ir
counter of the current depth
Definition: fastadd.cxx:49
makeTRTBarrelCans.dy
tuple dy
Definition: makeTRTBarrelCans.py:21
LArG4::Barrel::Geometry::m_detectorName
Gaudi::Property< std::string > m_detectorName
Definition: LArBarrelGeometry.h:64
LArCoudeAbsorbers::YCentCoude
double YCentCoude(int stackid, int cellid) const
Definition: LArCoudeAbsorbers.h:20
y
#define y
python.CaloAddPedShiftConfig.int
int
Definition: CaloAddPedShiftConfig.py:45
LArG4::Barrel::Geometry::m_delta
double * m_delta
Definition: LArBarrelGeometry.h:95
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
LArG4::Barrel::Geometry::m_zMaxBarrelDMMargin
double m_zMaxBarrelDMMargin
Definition: LArBarrelGeometry.h:76
LArStraightAbsorbers.h
makeTRTBarrelCans.dx
tuple dx
Definition: makeTRTBarrelCans.py:20
LArStraightAbsorbers::Cosu
double Cosu(int stackid, int cellid) const
Definition: LArStraightAbsorbers.h:28
LArG4::Barrel::Geometry::m_xc
double * m_xc
Definition: LArBarrelGeometry.h:93
LArStraightElectrodes::GetInstance
static const LArStraightElectrodes * GetInstance(const std::string &strDetector="")
Definition: LArStraightElectrodes.cxx:12
physics_parameters.parameters
parameters
Definition: physics_parameters.py:144
LArG4::Barrel::Geometry::m_NRphi
G4int m_NRphi
Definition: LArBarrelGeometry.h:107
LArG4::Barrel::Geometry::m_rMaxAccordion
double m_rMaxAccordion
Definition: LArBarrelGeometry.h:73
drawFromPickle.sin
sin
Definition: drawFromPickle.py:36
LArGeo::VDetectorParameters::GetInstance
static const VDetectorParameters * GetInstance()
Definition: VDetectorParameters.cxx:29
LArG4::Barrel::Geometry::m_NCellMax
int m_NCellMax
Definition: LArBarrelGeometry.h:81
LArG4::Barrel::Geometry::m_zMaxBarrel
double m_zMaxBarrel
Definition: LArBarrelGeometry.h:75
LArG4::Barrel::Geometry::m_rMinAccordion
double m_rMinAccordion
Definition: LArBarrelGeometry.h:72
LArStraightElectrodes::HalfLength
double HalfLength(int stackid, int cellid) const
Definition: LArStraightElectrodes.h:28