ATLAS Offline Software
HGTD_DetectorFactory.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3  */
4 
5 /* Three-ring detector layout, created by Christian and David
6  * Sep 2020 Lianyou SHAN merged
7  * hgtdlayout-master/place_modules_option2.py by Christina Agapopoulou
8  * into LArGeoModel/LArGeoEndcap/EndcapCryostatConstruction in R20.20.14.6
9  * Dec 2020 Lianyou SHAN integrate 2-ring layout
10  */
11 
13 
14 
15 
18 #include "StoreGate/StoreGateSvc.h" // For alignment getAlignableFolderType()
21 
23 #include "GeoModelKernel/GeoNameTag.h"
24 #include "GeoModelKernel/GeoIdentifierTag.h"
25 #include "GeoModelKernel/GeoMaterial.h"
26 #include "GeoModelKernel/GeoTransform.h"
27 #include "GeoModelKernel/GeoAlignableTransform.h"
28 #include "GeoModelKernel/GeoTorus.h"
29 #include "GeoModelKernel/GeoTube.h"
30 #include "GeoModelKernel/GeoBox.h"
31 #include "GeoModelKernel/GeoPhysVol.h"
32 #include "GeoModelKernel/GeoFullPhysVol.h"
38 #include "GaudiKernel/SystemOfUnits.h"
39 
41 
45 
48 
52 
53 #include <sstream>
54 #include <cmath>
55 
56 using namespace std;
57 using namespace InDetDD;
58 
60  InDetDD::DetectorFactoryBase( athComps ),
61  m_athComps( athComps ),
62  m_materialMgr( nullptr ),
63  m_geomVersion( -1 ),
64  m_outputIdfr( false ) {
65  // create the detector manager
67 
68  ATH_MSG_INFO( "HGTD geometry from hard-coded definition - No Information being taken from Geometry Tag!" );
69 
70 
71  // Create SiCommonItems. These are items that are shared by all elements
72  m_commonItems = std::make_unique<const InDetDD::SiCommonItems>(m_athComps->getIdHelper());
73 
74  // temporarily hardcode the HGTD version to build until the geo db has been updated with tables for 3-ring layout
75  // m_geomVersion = 0; // two-ring layout
76  m_geomVersion = 1; // three-ring layout
77 }
78 
80  // NB the detector manager (m_detectorManager) is stored in the detector store by the Tool and so we don't delete it.
81 }
82 
85  return;
86 }
87 
88 void HGTD_DetectorFactory::create(GeoPhysVol* world) {
89 
90  ATH_MSG_INFO( "Building HGTD detector");
91 
92  // initialize the geometry parameters
93  // Originally taken from geometry db, but now fully hard-coded until move to GMX implementation
95 
96  // for now the position of the HGTD mother volumes is hardcoded - TODO: take from db!
97  constexpr float zMother = 3482.5;
98 
99  // build logical volumes for the two endcaps
100  const GeoLogVol* positiveEndcapLogicalVolume = buildEndcapLogicalVolume(true);
101  const GeoLogVol* negativeEndcapLogicalVolume = buildEndcapLogicalVolume(false);
102 
103  // create and place positive endcap
104  world->add(new GeoNameTag("HGTD_Pos"));
105  world->add(new GeoIdentifierTag(9));
106  ATH_MSG_INFO( "HGTD_Pos mother volume will be placed at z = " << zMother << " mm" );
107  world->add(new GeoTransform(GeoTrf::TranslateZ3D(zMother)));
108  GeoVPhysVol* endcapPos = build( positiveEndcapLogicalVolume, true);
109  world->add( endcapPos );
110  m_detectorManager->addTreeTop( endcapPos);
111 
112  // create and place negative endcap
113  world->add(new GeoNameTag("HGTD_Neg"));
114  world->add(new GeoIdentifierTag(-9));
115  ATH_MSG_INFO( "HGTD_Neg mother volume will be placed at z = " << -zMother << " mm" );
116  world->add(new GeoTransform(GeoTrf::TranslateZ3D(-zMother)));
117  world->add(new GeoTransform(GeoTrf::RotateY3D(180.0*Gaudi::Units::deg)));
118  GeoVPhysVol* endcapNeg = build( negativeEndcapLogicalVolume, false);
119  world->add( endcapNeg );
120  m_detectorManager->addTreeTop( endcapNeg );
121 
122  // Add SiCommonItems to HGTD_DetectorManager to hold and delete it.
124 
125  return;
126 }
127 
128 // initialize the geometry parameters (now fully hard-coded until move to GMX implementation)
130 
131  // retrieve the material manager (can't use ATH_CHECK macros within create(), it seems..)
132  StatusCode sc = detStore()->retrieve(m_materialMgr, std::string("MATERIALS"));
133  if (sc != StatusCode::SUCCESS) {
134  ATH_MSG_ERROR("Cannot retrieve material manager from DetStore");
135  }
136 
137  // temporarily hard-code custom materials - eventually will be defined in xml once HGTD migrates to GeoModelXML detector description
138 
139  GeoMaterial* CFRP = new GeoMaterial("hgtd::CFRP", 1.78*(CLHEP::gram / CLHEP::cm3)); // copy of sct::CFRP used in 21.9
140  CFRP->add(m_materialMgr->getElement("Carbon"), 0.92);
141  CFRP->add(m_materialMgr->getElement("Hydrogen"), 0.02);
142  CFRP->add(m_materialMgr->getElement("Oxygen"), 0.05);
143  m_materialMgr->addMaterial("hgtd", CFRP);
144 
145  GeoMaterial* Honeycomb = new GeoMaterial("hgtd::Honeycomb", 0.042*(CLHEP::gram / CLHEP::cm3)); // copy of muo::Honeycomb used in 21.9
146  Honeycomb->add(m_materialMgr->getElement("Carbon"), 0.88);
147  Honeycomb->add(m_materialMgr->getElement("Hydrogen"), 0.11);
148  m_materialMgr->addMaterial("hgtd", Honeycomb);
149 
150  GeoMaterial* Peek = new GeoMaterial("hgtd::Peek", 1.3*(CLHEP::gram / CLHEP::cm3)); // copy of pix::Peek used in 21.9
151  Peek->add(m_materialMgr->getElement("Hydrogen"), 0.04);
152  Peek->add(m_materialMgr->getElement("Carbon"), 0.79);
153  Peek->add(m_materialMgr->getElement("Oxygen"), 0.16);
154  m_materialMgr->addMaterial("hgtd", Peek);
155 
156  GeoMaterial* CO2_Liquid = new GeoMaterial("hgtd::CO2_Liquid", 1.032*(CLHEP::gram / CLHEP::cm3)); // copy of pix::CO2_Liquid used in 21.9
157  CO2_Liquid->add(m_materialMgr->getElement("Carbon"), 0.27);
158  CO2_Liquid->add(m_materialMgr->getElement("Oxygen"), 0.72);
159  m_materialMgr->addMaterial("hgtd", CO2_Liquid);
160 
161  GeoMaterial* CO2 = new GeoMaterial("hgtd::CO2", 0.001842*(CLHEP::gram / CLHEP::cm3)); // copy of trt::CO2 used in 21.9
162  CO2->add(m_materialMgr->getElement("Carbon"), 0.27);
163  CO2->add(m_materialMgr->getElement("Oxygen"), 0.72);
164  m_materialMgr->addMaterial("hgtd", CO2);
165 
166  GeoMaterial* CFiberSupport = new GeoMaterial("hgtd::CFiberSupport", 0.189*(CLHEP::gram / CLHEP::cm3)); // copy of sct::CFiberSupport used in 21.9
167  CFiberSupport->add(m_materialMgr->getElement("Carbon"), 1.0);
168  m_materialMgr->addMaterial("hgtd", CFiberSupport);
169 
170  GeoMaterial* CuKapton = new GeoMaterial("hgtd::CuKapton", 2.94*(CLHEP::gram / CLHEP::cm3)); // copy of sct::CuKapton used in 21.9
171  CuKapton->add(m_materialMgr->getElement("Copper"), 0.61);
172  CuKapton->add(m_materialMgr->getElement("Carbon"), 0.26);
173  CuKapton->add(m_materialMgr->getElement("Hydrogen"), 0.01);
174  CuKapton->add(m_materialMgr->getElement("Oxygen"), 0.08);
175  CuKapton->add(m_materialMgr->getElement("Nitrogen"), 0.02);
176  m_materialMgr->addMaterial("hgtd", CuKapton);
177 
178  GeoMaterial* BoratedPolyethelyne = new GeoMaterial("hgtd::BoratedPolyethelyne", 0.99*(CLHEP::gram / CLHEP::cm3)); // copy of LAr::BoratedPolyethelyne used in 21.9
179  BoratedPolyethelyne->add(m_materialMgr->getElement("Hydrogen"), 0.13);
180  BoratedPolyethelyne->add(m_materialMgr->getElement("Carbon"), 0.81);
181  BoratedPolyethelyne->add(m_materialMgr->getElement("Boron"), 0.05);
182  m_materialMgr->addMaterial("hgtd", BoratedPolyethelyne);
183 
184  GeoMaterial* FEBoards = new GeoMaterial("hgtd::FEBoards", 0.99*(CLHEP::gram / CLHEP::cm3)); // copy of LAr::FEBoards used in 21.9
185  FEBoards->add(m_materialMgr->getElement("Silicon"), 0.27);
186  FEBoards->add(m_materialMgr->getElement("Oxygen"), 0.34);
187  FEBoards->add(m_materialMgr->getElement("Copper"), 0.28);
188  FEBoards->add(m_materialMgr->getElement("Hydrogen"), 0.01);
189  FEBoards->add(m_materialMgr->getElement("Carbon"), 0.09);
190  m_materialMgr->addMaterial("hgtd", FEBoards);
191 
192  GeoMaterial* Epoxy = new GeoMaterial("hgtd::Epoxy", 1*(CLHEP::gram / CLHEP::cm3)); // copy of sct::Epoxy used in 21.9
193  Epoxy->add(m_materialMgr->getElement("Carbon"), 0.76);
194  Epoxy->add(m_materialMgr->getElement("Hydrogen"), 0.07);
195  Epoxy->add(m_materialMgr->getElement("Oxygen"), 0.16);
196  m_materialMgr->addMaterial("hgtd", Epoxy);
197 
198  // Hardcoded box parameters taken from geometry db:
199 
200  // Node: HGTDBox BOX DX DY DZ ZPOS MATERIAL
201  m_boxVolPars["HGTDModule0"] = {"HGTDModule0", 11, 20, 1.75, 0, "std::Air"};
202  m_boxVolPars["HGTDModule1"] = {"HGTDModule1", 11, 20, 1.75, 0, "std::Air"};
203  m_boxVolPars["HGTDModule2"] = {"HGTDModule2", 11, 20, 1.75, 0, "std::Air"};
204  m_boxVolPars["HGTDModule3"] = {"HGTDModule3", 11, 20, 1.75, 0, "std::Air"};
205  m_boxVolPars["HGTD::Hybrid"] = {"HGTD::Hybrid", 10.25, 20, .175, 0, "hgtd::CuKapton"};
206  m_boxVolPars["HGTD::GlueSensor"] = {"HGTD::GlueSensor", 10.25, 20, .04, 0, "hgtd::Epoxy"};
207  m_boxVolPars["HGTD::GlueAsic"] = {"HGTD::GlueAsic", 11, 20, .04, 0, "hgtd::Epoxy"};
208  m_boxVolPars["HGTDSiSensor0"] = {"HGTDSiSensor0", 10.25, 20, .025, 0, "std::Silicon"};
209  m_boxVolPars["HGTDSiSensor1"] = {"HGTDSiSensor1", 10.25, 20, .025, 0, "std::Silicon"};
210  m_boxVolPars["HGTDSiSensor2"] = {"HGTDSiSensor2", 10.25, 20, .025, 0, "std::Silicon"};
211  m_boxVolPars["HGTDSiSensor3"] = {"HGTDSiSensor3", 10.25, 20, .025, 0, "std::Silicon"};
212  m_boxVolPars["HGTD::LGADInactive"] = {"HGTD::LGADInactive", 10.25, 20, .1, 0, "std::Silicon"};
213  m_boxVolPars["HGTD::ASIC"] = {"HGTD::ASIC", 11, 20, .15, 0, "std::Silicon"};
214 
215  // Add a dummy entry that will be used to leave some space - no volume will actually be created for this
216  // needed after fix of ASIC thickness (and material) in HGTD-TDR-01 tag (ATLAS-P2-ITK-17-04-02 and later), compared to HGTD-TDR-00
217  double moduleSpaceHalfZ = 0.225;
218  m_boxVolPars["HGTD::ModuleSpace"] = {"HGTD::ModuleSpace", 11, 20, moduleSpaceHalfZ, 0, "std::Air"};
219 
220 
221 
222  // Node: HGTDTubs TUBE RMIN RMAX DZ ZPOS MATERIAL
223  m_cylVolPars["HGTD_mother"] = {"HGTD_mother", 100, 1100, 62.5, -3252, "std::Air"};
224  m_cylVolPars["HGTD::FrontCover"] = {"HGTD::FrontCover", 120, 1000, 7.5, 0, "hgtd::CFiberSupport"};
225  m_cylVolPars["HGTD::FlexPackage"] = {"HGTD::FlexPackage", 120, 660, 2, 0, "std::Air"};
226  m_cylVolPars["HGTD::FlexTube"] = {"HGTD::FlexTube", 120, 660, .175, 0, "hgtd::CuKapton"};
227  m_cylVolPars["HGTD::ModuleLayer0"] = {"HGTD::ModuleLayer0", 120, 660, 3.75, 0, "std::Air"};
228  m_cylVolPars["HGTD::ModuleLayer1"] = {"HGTD::ModuleLayer1", 120, 660, 3.75, 0, "std::Air"};
229  m_cylVolPars["HGTD::ModuleLayer2"] = {"HGTD::ModuleLayer2", 120, 660, 3.75, 0, "std::Air"};
230  m_cylVolPars["HGTD::ModuleLayer3"] = {"HGTD::ModuleLayer3", 120, 660, 3.75, 0, "std::Air"};
231  m_cylVolPars["HGTD::CoolingPlate"] = {"HGTD::CoolingPlate", 120, 920, 3, 0, "std::Aluminium"};
232  m_cylVolPars["HGTD::SupportPlate"] = {"HGTD::SupportPlate", 120, 660, .5, 0, "std::Aluminium"};
233  m_cylVolPars["HGTD::ToleranceFront"] = {"HGTD::ToleranceFront", 120, 660, 1, 0, "std::Air"};
234  m_cylVolPars["HGTD::ToleranceBack"] = {"HGTD::ToleranceBack", 120, 660, 1, 0, "std::Air"};
235  m_cylVolPars["HGTD::ToleranceMid"] = {"HGTD::ToleranceMid", 120, 660, 1, 0, "std::Air"};
236  m_cylVolPars["HGTD::ModeratorIn"] = {"HGTD::ModeratorIn", 120, 900, 15, 0, "hgtd::BoratedPolyethelyne"};
237  m_cylVolPars["HGTD::ModeratorOut"] = {"HGTD::ModeratorOut", 120, 1100, 10, 0, "hgtd::BoratedPolyethelyne"};
238  m_cylVolPars["HGTD::BackCover"] = {"HGTD::BackCover", 120, 1100, 4, 0, "hgtd::CFiberSupport"};
239  m_cylVolPars["HGTD::PeriphElec"] = {"HGTD::PeriphElec", 674, 900, 1, 2, "hgtd::FEBoards"};
240 
241  m_cylVolPars["HGTD::InnerRCover1"] = {"HGTD::InnerRCover1", 110., 111., 105./2, -10., "hgtd::CFRP"};
242  // the InnerRCover bulk should be 70% aerogel and 30% honeycomb made from "aradime" (not defined - using "hgtd::Honeycomb" for now)
243  // proportions should be 50/50 by weight, which is used for GeoMaterial fractions
244  // TODO: these should be double-checked, or at least that the density/weight matches engineering drawings
245  GeoMaterial* innerRCoverBulkMaterial = new GeoMaterial("hgtd::AerogelAndHoneycomb", 0.17*(CLHEP::gram / CLHEP::cm3));
246  innerRCoverBulkMaterial->add(m_materialMgr->getMaterial("std::Aerogel"), 0.5);
247  innerRCoverBulkMaterial->add(m_materialMgr->getMaterial("hgtd::Honeycomb"), 0.5);
248  m_materialMgr->addMaterial("hgtd", innerRCoverBulkMaterial);
249  m_cylVolPars["HGTD::InnerRCover2"] = {"HGTD::InnerRCover2", 111., 119., 105./2, -10., "hgtd::AerogelAndHoneycomb"};
250  m_cylVolPars["HGTD::InnerRCover3"] = {"HGTD::InnerRCover3", 119., 120., 105./2, -10., "hgtd::CFRP"};
251  m_cylVolPars["HGTD::OuterRCover"] = {"HGTD::OuterRCover", 980., 1000., 82./2, -6.5, "hgtd::Peek"};
252  m_cylVolPars["HGTD::PeripheralCoolingLines"] = {"HGTD::PeripheralCoolingLines", 920., 980., 3./2, 31., "std::SSteel"};
253  // TODO: outer cover should be 40% "hgtd::Peek" and 60% electrical connectors (unclear material)
254 
255  m_cylVolPars["HGTD::CoolingTube"] = {"HGTD::CoolingTubes", 0, 0, 2.0, 0, "std::Titanium"};
256  // Coolant should be 50% liquid and 50% gas CO2 ("hgtd::CO2")
257  GeoMaterial* coolantMaterial = new GeoMaterial("hgtd::CO2CoolantMix", 0.55*(CLHEP::gram / CLHEP::cm3));
258  coolantMaterial->add(m_materialMgr->getMaterial("hgtd::CO2_Liquid"), 0.5);
259  coolantMaterial->add(m_materialMgr->getMaterial("hgtd::CO2"), 0.5);
260  m_materialMgr->addMaterial("hgtd", coolantMaterial);
261  m_cylVolPars["HGTD::CoolingTubeFluid"] = {"HGTD::CoolingTubeFluid", 0, 0, 1.5, 0, "hgtd::CO2CoolantMix"};
262 
263 
264 
265  // These parameters were not in the db (they don't fit into the cylinder or box structures used above)
266  m_hgtdPars = { 320., // rMid
267  640., // rOuter - only used in one place, and there 20 mm is added to it...
268  0., // disk1Rotation (in degrees)
269  15., // disk2Rotation (in degrees)
270  1., // rowSpaceSide
271  4., // rowBacksideInnerShift
272  17., // rowBacksideOuterShift
273  1.5, // moduleSpaceInner
274  12.5, // moduleSpaceOuter
275  0.456 // flexSheetSpacing
276  };
277 
278  return;
279 }
280 
281 // prepare an envelope for one HGTD side
282 GeoLogVol* HGTD_DetectorFactory::buildEndcapLogicalVolume(bool isPositiveSide) {
283 
284  // build the solid volume
285  GeoTube* world_solid_hgtd = new GeoTube(m_cylVolPars["HGTD_mother"].rMin, m_cylVolPars["HGTD_mother"].rMax,
286  m_cylVolPars["HGTD_mother"].zHalf);
287 
288  // build the logical volume
289  std::string name = isPositiveSide ? "HGTD_PositiveEndcap" : "HGTD_NegativeEndcap";
290  GeoLogVol* world_logical_hgtd = new GeoLogVol( name.c_str(), world_solid_hgtd,
291  m_materialMgr->getMaterial( m_cylVolPars[ "HGTD_mother"].material) );
292 
293  return world_logical_hgtd;
294 }
295 
296 
297 GeoVPhysVol* HGTD_DetectorFactory::build( const GeoLogVol* logicalEnvelope, bool bPos) {
298 
299  ATH_MSG_INFO( "**************************************************");
300  ATH_MSG_INFO( " Building HGTD geometry , side = " << bPos << " ");
301  ATH_MSG_INFO( "**************************************************" );
302 
303  GeoFullPhysVol* HGTDparent = new GeoFullPhysVol( logicalEnvelope );
304 
305  // to be calculated from parameters in db using map
306  double motherHalfZ = ((GeoTube*) HGTDparent->getLogVol()->getShape())->getZHalfLength();
307  double modulePackageHalfZtot = 3.5/2 + 4./2; // including flex - can we not get this from the db numbers? /CO
308 
309  double modulePackageHalfZ = 2*m_boxVolPars["HGTD::GlueSensor"].zHalf + m_boxVolPars["HGTDSiSensor0"].zHalf
310  + m_boxVolPars["HGTD::LGADInactive"].zHalf + m_boxVolPars["HGTD::ASIC"].zHalf
311  + m_boxVolPars["HGTD::Hybrid"].zHalf + m_boxVolPars["HGTD::ModuleSpace"].zHalf;
312 
313  // add volumes by key name to ordered vector, outside in (from larger z to smaller)
314  std::vector<std::string> hgtdVolumes;
315  hgtdVolumes.push_back("HGTD::ModeratorOut"); // Out as in outside the vessel
316  hgtdVolumes.push_back("HGTD::BackCover");
317  hgtdVolumes.push_back("HGTD::ToleranceBack");
318  hgtdVolumes.push_back("HGTD::ModeratorIn"); // In as in inside the vessel
319 
320  hgtdVolumes.push_back("HGTD::ModuleLayer3");
321  hgtdVolumes.push_back("HGTD::SupportPlate");
322  hgtdVolumes.push_back("HGTD::CoolingPlate");
323  hgtdVolumes.push_back("HGTD::SupportPlate");
324  hgtdVolumes.push_back("HGTD::ModuleLayer2");
325 
326  hgtdVolumes.push_back("HGTD::ToleranceMid");
327 
328  hgtdVolumes.push_back("HGTD::ModuleLayer1");
329  hgtdVolumes.push_back("HGTD::SupportPlate");
330  hgtdVolumes.push_back("HGTD::CoolingPlate");
331  hgtdVolumes.push_back("HGTD::SupportPlate");
332  hgtdVolumes.push_back("HGTD::ModuleLayer0");
333 
334  hgtdVolumes.push_back("HGTD::ToleranceFront");
335  hgtdVolumes.push_back("HGTD::FrontCover");
336  // Important - these must come last since they will otherwise shift positions of the previous volumes!
337  hgtdVolumes.push_back("HGTD::InnerRCover1"); // don't reorder!
338  hgtdVolumes.push_back("HGTD::InnerRCover2"); // don't reorder!
339  hgtdVolumes.push_back("HGTD::InnerRCover3"); // don't reorder!
340  hgtdVolumes.push_back("HGTD::OuterRCover"); // don't reorder!
341  hgtdVolumes.push_back("HGTD::PeripheralCoolingLines"); // don't reorder!
342 
343  // Now build up the solid, logical and physical volumes as appropriate (starting from the outermost volume)
344  // We first start with the volumes we'll reuse several times
345 
347  // FLEX PACKAGE VOLUMES //
349 
350  // Flex package volume modeled as 8 concentric flex sheets with progressively larger inner radius
351  // Order of sheets depend on whether package is for front or back of a cooling plate
352  // First calculate the inner radii for the flex sheets
353  GeoCylVolParams packagePars = m_cylVolPars["HGTD::FlexPackage"];
354  GeoCylVolParams flexPars = m_cylVolPars["HGTD::FlexTube"];
355  std::vector<double> flexSheetInnerR;
356  double currentInnerR = 144.; // adding flex sheets from the second sensor (all have the hybrid already)
357  for (int flexSheet = 0; flexSheet < 8; flexSheet++) {
358  flexSheetInnerR.push_back(currentInnerR);
359  // set the inner radius for the next flex sheet, increased by two module heights and two radius-dependent spaces per sheet
360  currentInnerR += m_boxVolPars["HGTDModule0"].xHalf*2 * (2 + 2 * (flexSheet < 4 ? 0.2 : 0.8) );
361  }
362 
363  // build up the two flex volumes for front (0) and back (1) sides
364  GeoPhysVol* flexPackagePhysical[2] = {};
365  for (int flexVolume = 0; flexVolume < 2; flexVolume++) {
366  std::vector<double> rInner = flexSheetInnerR;
367  if (flexVolume) reverse(rInner.begin(), rInner.end()); // reverse order for backside flex package
368 
369  GeoTube* flexPackageSolid = new GeoTube(packagePars.rMin, packagePars.rMax, packagePars.zHalf);
370  GeoLogVol* flexPackageLogical = new GeoLogVol(packagePars.name, flexPackageSolid, m_materialMgr->getMaterial(packagePars.material));
371  flexPackagePhysical[flexVolume] = new GeoPhysVol(flexPackageLogical);
372  // build up a volume of flex cables, starting in z at half a flex layer from the edge of the flex package volume
373  double flexZoffset = packagePars.zHalf - flexPars.zHalf;
374  for (int flexSheet = 0; flexSheet < 8; flexSheet++) {
375  GeoTube* hgtdFlexSolid = new GeoTube(rInner[flexSheet], flexPars.rMax, flexPars.zHalf);
376  GeoLogVol* hgtdFlexLogical = new GeoLogVol("HGTD::FlexTube"+std::to_string(flexSheet),
377  hgtdFlexSolid, m_materialMgr->getMaterial(flexPars.material));
378  GeoPhysVol* hgtdFlexPhysical = new GeoPhysVol(hgtdFlexLogical);
379  flexPackagePhysical[flexVolume]->add(new GeoTransform(GeoTrf::TranslateZ3D(flexZoffset)));
380  flexPackagePhysical[flexVolume]->add(hgtdFlexPhysical);
381  // print out a line for each flex layer
382  ATH_MSG_DEBUG( "Flex layer (" << (flexSheet ? "front" : "back") << ")" << flexSheet << ", Rmin = " << std::setw(5)
383  << rInner[flexSheet] << " mm, flexZoffset = " << flexZoffset << " mm" );
384  flexZoffset = flexZoffset - m_hgtdPars.flexSheetSpacing;
385  }
386  }
387 
389  // COOLING TUBES //
391 
392  // make list of radii of cooling tubes
393  std::vector<double> coolingTubeRadii;
394  double coolingTubeRadius = 130.;
395  coolingTubeRadii.push_back(coolingTubeRadius);
396 
397  // two-ring layout
398  if (m_geomVersion == 0) {
399  ATH_MSG_INFO("Will now calculate cooling-loop positions for the two-ring layout");
400  for (int i = 0; i < 18; i++) {
401  coolingTubeRadius += (418-130.)/18;
402  coolingTubeRadii.push_back(coolingTubeRadius);
403  }
404  for (int i = 0; i < 12; i++) {
405  coolingTubeRadius += (658-418.)/14;
406  coolingTubeRadii.push_back(coolingTubeRadius);
407  }
408  coolingTubeRadius = 710.;
409  coolingTubeRadii.push_back(coolingTubeRadius);
410  for (int i = 0; i < 7; i++) {
411  coolingTubeRadius += (890-710.)/6;
412  coolingTubeRadii.push_back(coolingTubeRadius);
413  }
414  }
415  else if (m_geomVersion == 1) {
416  ATH_MSG_INFO("Will now calculate cooling-loop positions for the three-ring layout");
417  // inner part, even spacing from 130 mm to 674 mm, 35 rings with 16 mm spacing (first one already placed above)
418  int numberOfLoops = 34;
419  float loopDistance = (674.-130.)/numberOfLoops; // in mm
420  for (int i = 0; i < numberOfLoops; i++) {
421  coolingTubeRadius += loopDistance;
422  coolingTubeRadii.push_back(coolingTubeRadius);
423  }
424  // outer part, even spacing from 720 mm to 900 mm, 7 rings with 30 mm spacing
425  coolingTubeRadius = 720;
426  coolingTubeRadii.push_back(coolingTubeRadius);
427  numberOfLoops = 6;
428  loopDistance = (900.-720.)/numberOfLoops;
429  for (int i = 0; i < numberOfLoops; i++) {
430  coolingTubeRadius += loopDistance;
431  coolingTubeRadii.push_back(coolingTubeRadius);
432  }
433  }
434  ATH_MSG_DEBUG( "Cooling tubes will be created at the following radii (" << coolingTubeRadii.size() << " in total):");
435  for (size_t i = 0; i < coolingTubeRadii.size(); i++) {
436  ATH_MSG_DEBUG( " R = " << coolingTubeRadii[i] << " mm" );
437  }
438 
440  // PERIPHERAL ELECTRONICS VOLUME //
442 
443  //build peripheral electronics
444  GeoCylVolParams periphElPars = m_cylVolPars["HGTD::PeriphElec"];
445  GeoTube* periphElec_solid = new GeoTube(periphElPars.rMin, periphElPars.rMax, periphElPars.zHalf);
446  GeoLogVol* periphElec_log = new GeoLogVol(periphElPars.name, periphElec_solid, m_materialMgr->getMaterial(periphElPars.material));
447  GeoPhysVol* periphElec_phys = new GeoPhysVol(periphElec_log);
448 
449  std::array< GeoPhysVol*, 4 > moduleLayerPhysical = {}; // array of pointers to the physical volumes for the module layers which need special care
450 
452  // BUILD UP ALL MAIN VOLUMES IN SEQUENCE //
454 
455  // now build up the volumes in the order specified in the vector
456  double zModuleLayerF = 0.;
457  double zModuleLayerB = 0.;
458  for (size_t vol = 0; vol < hgtdVolumes.size(); vol++) {
459 
460  std::string v = hgtdVolumes[vol];
461 
462  // calculate local z offsets for each main volume sequentially
463  if (vol == 0) // special treatment for the first one
464  m_cylVolPars[v].zOffsetLocal = motherHalfZ - m_cylVolPars[v].zHalf;
465 
466  // All but the InnerRCover, OuterRCover and peripheral cooling lines are placed relative to other components,
467  // but the zOffsetLocal parameter of these volumes is left as read from the db
468  else {
469  if (v.substr(9,8) != "erRCover" && v != "HGTD::PeripheralCoolingLines") {
470  std::string vPrev = hgtdVolumes[vol-1];
471  m_cylVolPars[v].zOffsetLocal = m_cylVolPars[vPrev].zOffsetLocal - m_cylVolPars[vPrev].zHalf - m_cylVolPars[v].zHalf;
472  }
473  }
474 
475  // skip the tolerances - we don't actually want to create volumes for the space
476  if (v.substr(0,15) == "HGTD::Tolerance") continue;
477 
478  float safety = 0.;
479  if (v.substr(0,17) == "HGTD::ModuleLayer")
480  safety = 10.;
481 
482  // a disk volume to hold 4 quadrants
483  GeoTube* hgtdSubVolumeSolid = new GeoTube(m_cylVolPars[v].rMin, m_cylVolPars[v].rMax+safety, m_cylVolPars[v].zHalf);
484  GeoLogVol* hgtdSubVolumeLogical = new GeoLogVol(m_cylVolPars[v].name, hgtdSubVolumeSolid, m_materialMgr->getMaterial(m_cylVolPars[v].material));
485  GeoPhysVol* hgtdSubVolumePhysical = new GeoPhysVol(hgtdSubVolumeLogical);
486 
487  // if building the cooling plate, also add peripheral electronics since position of those are relative to that of cooling plate
488  if (v == "HGTD::CoolingPlate") {
489  double zOffsetPeriphElec = m_cylVolPars[v].zHalf + periphElPars.zOffsetLocal + periphElPars.zHalf;
490  // place two, one on each side of cooling plate
491  static constexpr std::array<int,2> signArr{1,-1};
492  for (int side = 0; side < 2; side++) {
493  //0, 1 index -> 1, -1 sign
494  HGTDparent->add(new GeoTransform(GeoTrf::TranslateZ3D(m_cylVolPars[v].zOffsetLocal + signArr[side]*zOffsetPeriphElec)));
495  HGTDparent->add(periphElec_phys);
496  }
497 
498  // and the CO2 cooling tubes inside the cooling plate
499  for (size_t i = 0; i < coolingTubeRadii.size(); i++) {
500  // the tube itself
501  GeoTorus* coolingTubeSolid = new GeoTorus(m_cylVolPars["HGTD::CoolingTubeFluid"].zHalf, m_cylVolPars["HGTD::CoolingTube"].zHalf,
502  coolingTubeRadii[i], 0, 2*M_PI);
503  GeoLogVol* coolingTubeLogical = new GeoLogVol("HGTD::CoolingTube", coolingTubeSolid,
504  m_materialMgr->getMaterial(m_cylVolPars["HGTD::CoolingTube"].material));
505  GeoPhysVol* coolingTubePhysical = new GeoPhysVol(coolingTubeLogical);
506  hgtdSubVolumePhysical->add(coolingTubePhysical); // no transformations needed, concentric with cooling plate and centered in z
507  // and the contents, i.e. the cooling fluid
508  GeoTorus* coolingFluidSolid = new GeoTorus(0, m_cylVolPars["HGTD::CoolingTubeFluid"].zHalf,
509  coolingTubeRadii[i], 0, 2*M_PI);
510  GeoLogVol* coolingFluidLogical = new GeoLogVol("HGTD::CoolingFluid", coolingFluidSolid,
511  m_materialMgr->getMaterial(m_cylVolPars["HGTD::CoolingTubeFluid"].material));
512  GeoPhysVol* coolingFluidPhysical = new GeoPhysVol(coolingFluidLogical);
513  hgtdSubVolumePhysical->add(coolingFluidPhysical); // no transformations needed, concentric with cooling plate and centered in z
514  }
515  }
516 
517  // module layer
518  if (v.substr(0,17) == "HGTD::ModuleLayer") {
519 
520  int layer = atoi(v.substr(17,1).c_str());
521 
522  // front and back side layers are treated differently: z position of flex and module layers, and rotation
523  double zFlex = 0.;
524  bool Lside = layer % 2;
525  if (Lside == 0) { // layers 0 and 2
526  zFlex = -modulePackageHalfZtot + m_cylVolPars["HGTD::FlexPackage"].zHalf;
527  zModuleLayerF = modulePackageHalfZtot - modulePackageHalfZ;
528  }
529  else { // layers 1 and 3
530  zFlex = modulePackageHalfZtot - m_cylVolPars["HGTD::FlexPackage"].zHalf;
531  zModuleLayerB = -modulePackageHalfZtot + modulePackageHalfZ;
532  }
533 
534  // place flex within module packages, at different positions depending on front or back or cooling plate
535  hgtdSubVolumePhysical->add(new GeoTransform(GeoTrf::TranslateZ3D(zFlex)));
536  hgtdSubVolumePhysical->add(flexPackagePhysical[(Lside ? 0 : 1)]);
537 
538  float diskRotation = layer <= 1 ? m_hgtdPars.disk1Rotation : m_hgtdPars.disk2Rotation;
539 
540  HGTDparent->add(new GeoTransform( GeoTrf::TranslateZ3D(m_cylVolPars[v].zOffsetLocal) *
541  GeoTrf::RotateZ3D(diskRotation*Gaudi::Units::deg)) );
542  // one needs to check this rotation against the "quadrot" will be used in the following
543 
544  HGTDparent->add( hgtdSubVolumePhysical );
545  moduleLayerPhysical[layer] = hgtdSubVolumePhysical;
546 
547  } // end of module package
548  else {
549  HGTDparent->add(new GeoTransform(GeoTrf::TranslateZ3D(m_cylVolPars[v].zOffsetLocal)));
550  HGTDparent->add(hgtdSubVolumePhysical);
551  }
552 
553  // print out info about each main volume
554  ATH_MSG_INFO( std::setw(20) << m_cylVolPars[v].name << " ( " << std::setw(20) << m_cylVolPars[v].material
555  << " ), local z = " << std::setw(6) << m_cylVolPars[v].zOffsetLocal
556  << " mm, Rmin = " << std::setw(4) << m_cylVolPars[v].rMin
557  << " mm, Rmax = " << std::setw(4) << m_cylVolPars[v].rMax
558  << " mm, DZ = " << std::setw(5) << m_cylVolPars[v].zHalf << " mm" );
559 
560  } // end loop over hgtdVolumes
561 
563  // MODULE VOLUMES //
565 
566  // components for the module
567  std::vector<std::string> moduleVolumes;
568  moduleVolumes.push_back("HGTD::GlueAsic");
569  moduleVolumes.push_back("HGTD::ASIC");
570  moduleVolumes.push_back("HGTD::LGADInactive");
571  moduleVolumes.push_back("SensorPlaceHolder"); // replaced below to get the numbered name right
572  moduleVolumes.push_back("HGTD::GlueSensor");
573  moduleVolumes.push_back("HGTD::Hybrid");
574  moduleVolumes.push_back("HGTD::ModuleSpace");
575 
576  int endcap = bPos ? +2 : -2;
577  double thickness = 2.*m_boxVolPars["HGTDSiSensor0"].zHalf;
578  InDetDD::HGTD_ModuleDesign* moduleDesign = createHgtdDesign( thickness );
579 
580  // create the module --> each for cell and with different names
581  // calculate the positions where modules should be placed in one quadrant
582 
583  int totMod = 0;
584  // this should be taken from DB or XML
585  unsigned int maxRows = 21;
586  if ( m_geomVersion == 0 ) maxRows = 18;
587 
588  std::array< PositionsInQuadrant, 4 > positions = prepareLayersFromQuadrants( maxRows ) ;
589  // inside m_geomVersion implicitly control 3-ring layout vs 2-ring
590 
591  mirrorPositionsAroundYaxis(positions);
592 
593  for (int layer = 0; layer < 4; layer++) {
594  if (m_outputIdfr) cout << "Layer #" << layer << std::endl;
595  // select from front vs back side of a disk
596  int Lside = layer % 2;
597 
598  std::vector<std::string> volumes = moduleVolumes;
599  if ( Lside != 0 ) reverse( volumes.begin(), volumes.end() ); // reverse order of components for backside modules
600 
601  std::string sensorName = std::string("HGTDSiSensor") + std::to_string(layer);
602  std::string moduleName = std::string("HGTDModule") + std::to_string(layer);
603 
604  // here we assumed all 4 layers share the same dimensions.
605  // As described at HGTD_DetectorFactory::reorderRows,
606  // the short edge of 4*2 cm module in the leading row is defined as local X/Width
607  // in ReadoutGeometry, this short edge is also defined as Eta, since the row is roughly along radius.
608  double moduleHalfWidth = m_boxVolPars[moduleName].xHalf; // 11m than 10 to hold wire bond
609  double moduleHalfHeight = m_boxVolPars[moduleName].yHalf;
610 
611  // loop over quadrants in the current layer
612  // take a prepared quadrant as protype
613  PositionsInQuadrant tmpQuadrant = positions[ layer ];
614  // The relative rotation between two disks is supposed to be defined/accounted within tmpQuadrant
615  for (int q = 0; q < 4; q++) {
616  float quadrot = q*90.;
617 
618  for ( unsigned int row = 0; row < maxRows; row ++ ) {
619  std::vector< ModulePosition > ModsPerRow = tmpQuadrant[ row ];
620 
621  // print #modules per row to fill HGTD_Identifier dictionary etc.
622  if ( m_outputIdfr && q == 0 ) std::cout << " Row #"<< row + 1 <<" :: " << ModsPerRow.size() << std::endl;
623 
624  for ( unsigned int mod = 0; mod < ModsPerRow.size(); mod ++ ) {
625  ModulePosition module = ModsPerRow[ mod ];
626 
627  double myx = -9999999.9 , myy = -9999999.9 , myrot = -9999999.9;
628  int myphi = -1 , myeta = - 1;
629  std::string module_string = formModuleName( layer, q, maxRows, row, mod, module, myx, myy, myrot, myphi, myeta );
630 
631  if ( module_string == "" || myrot == -9999999.9 || myeta == -1 )
632  ATH_MSG_WARNING ( " Please check the module at layer "<< layer <<" quadrant " << q <<" row "<< row <<" mod " << mod <<" not well retrieved ! " );
633 
634  // an hgtd module defined in the form of ( X, Y, Z )
635  GeoBox* moduleSolid = new GeoBox( moduleHalfWidth, moduleHalfHeight, modulePackageHalfZ);
636  GeoLogVol* moduleLogical = new GeoLogVol( moduleName + module_string, moduleSolid, m_materialMgr->getMaterial("std::Air"));
637  GeoFullPhysVol* modulePhysical = new GeoFullPhysVol( moduleLogical );
638 
639  // print out one module per layer
640  if ( q == 0 && row == 0 && mod == 0 )
641  ATH_MSG_DEBUG( "Will now build up an individual HGTD module of layer " << layer << " and quadrant " << q << " (" << module_string << ")" );
642 
643  // loop over components in module
644  for (size_t comp = 0; comp < volumes.size(); comp++) {
645  if (volumes[comp] == "SensorPlaceHolder") volumes[comp] = sensorName; // replace placeholder
646 
647  std::string c = volumes[comp];
648  // calculate local z offsets for each sensor component sequentially
649  if (comp == 0) // special treatment for the first one
650  m_boxVolPars[c].zOffsetLocal = modulePackageHalfZ - m_boxVolPars[c].zHalf;
651  else {
652  std::string cPrev = volumes[comp-1];
653  m_boxVolPars[c].zOffsetLocal = m_boxVolPars[cPrev].zOffsetLocal - m_boxVolPars[cPrev].zHalf - m_boxVolPars[c].zHalf;
654  }
655 
656  // skip the module space - we don't actually want to create volumes for the space
657  if (volumes[comp] == "HGTD::ModuleSpace") continue;
658 
659  double comp_halfx = m_boxVolPars[c].xHalf;
660  double comp_halfy = m_boxVolPars[c].yHalf;
661 
662  // and x offsets for those components that are smaller, to make room for wire bond of flex to ASIC which is larger than the sensor
663  double xOffsetLocal = moduleHalfWidth - comp_halfx;
664  // need tuning then dataBase : to make room for wire bond of flex to ASIC which is larger than the sensor
665 
666  GeoBox* sensorCompSolidVol = new GeoBox(comp_halfx, comp_halfy, m_boxVolPars[c].zHalf);
667  // No attachment?
668  std::string attach = (volumes[comp] == sensorName) ? "" : "_L" + std::to_string( layer ) + module_string;
669 
670  GeoLogVol* sensorCompLogicalVol = new GeoLogVol( m_boxVolPars[c].name+attach, sensorCompSolidVol,
672  GeoFullPhysVol* sensorCompPhysicalVol = new GeoFullPhysVol(sensorCompLogicalVol);
673 
674  if (volumes[comp] == sensorName) {
675  const HGTD_ID* hgtdId = dynamic_cast<const HGTD_ID*>( m_athComps->getIdHelper() );
676  Identifier idwafer = hgtdId->wafer_id( endcap, layer, myphi, myeta );
677 
678  // print only the first and last module of each row in the first quadrant
679  if ( q == 0 && ( mod == 0 || mod == ( ModsPerRow.size() - 1 ) ) && !m_outputIdfr ) {
680  ATH_MSG_DEBUG( " waferHash : " << hgtdId->wafer_hash( idwafer )
681  << " upon HGTD_ID => ec: " << endcap << ", layer: " << layer << ", quadrant: " << q
682  << ", row: " << myphi <<", module: "<< myeta );
683  ATH_MSG_DEBUG( " HGTD Module: " << m_boxVolPars[c].name+module_string << ", posX: " << myx << ", posY: " << myy << ", rot: " << quadrot + myrot );
684  }
685 
686  InDetDD::HGTD_DetectorElement* detElement = new InDetDD::HGTD_DetectorElement(idwafer, moduleDesign, sensorCompPhysicalVol, m_commonItems.get());
687  m_detectorManager->addDetectorElement( detElement );
688 
689  GeoTrf::Transform3D sensorTransform = GeoTrf::TranslateZ3D(m_boxVolPars[c].zOffsetLocal)*GeoTrf::TranslateX3D(xOffsetLocal);
690  GeoAlignableTransform* xform = new GeoAlignableTransform(sensorTransform);
691 
692  modulePhysical->add( xform );
693  modulePhysical->add( sensorCompPhysicalVol );
694 
695  totMod ++;
696  }
697  else {
698  modulePhysical->add(new GeoTransform(GeoTrf::TranslateZ3D(m_boxVolPars[c].zOffsetLocal)*GeoTrf::TranslateX3D(xOffsetLocal)));
699  modulePhysical->add(sensorCompPhysicalVol);
700  }
701 
702  // print out each module component
703  if ( mod == 0 && q == 0 && volumes[comp] != sensorName )
704  ATH_MSG_DEBUG( std::setw(20) << m_boxVolPars[c].name << " ( " << std::setw(15) << m_boxVolPars[c].material
705  << " ), in-sensor-layer local z = " << std::setw(7) << m_boxVolPars[c].zOffsetLocal << " mm"
706  << ", DX = " << std::setw(5) << m_boxVolPars[c].xHalf << " mm"
707  << ", DY = " << std::setw(5) << m_boxVolPars[c].yHalf << " mm"
708  << ", DZ = " << std::setw(5) << m_boxVolPars[c].zHalf << " mm" );
709  } // end of components loop
710 
711  double zModule = ( Lside == 0 ? zModuleLayerF : zModuleLayerB );
712 
713  GeoTransform* moduleTransform = new GeoTransform( GeoTrf::TranslateZ3D(zModule) *
714  GeoTrf::TranslateX3D(myx) *
715  GeoTrf::TranslateY3D(myy) *
716  GeoTrf::RotateZ3D( ( quadrot + myrot )*Gaudi::Units::deg) );
717  moduleLayerPhysical[layer]->add( moduleTransform );
718  moduleLayerPhysical[layer]->add( modulePhysical );
719  } //end of modules loop
720  ATH_MSG_DEBUG( "Done placing modules for row " << row );
721  } // end of row loop
722  ATH_MSG_DEBUG( "Done placing modules for quadrant " << q );
723  } // end of quadrants loop
724  ATH_MSG_DEBUG( "Done placing modules for layer " << layer );
725  }
726 
727  ATH_MSG_INFO( "**************************************************" );
728  ATH_MSG_INFO( " Done building HGTD with " << totMod <<" modules " );
729  ATH_MSG_INFO( "**************************************************" );
730 
731  return HGTDparent;
732 }
733 
734 // backwards compatibility two-ring layout used for TDR studies
735 // careful implicit dependence on m_geomVersion to make 3-ring layout different from 2-ring
736 std::array< PositionsInQuadrant, 4 > HGTD_DetectorFactory::prepareLayersFromQuadrants( unsigned int nRows ) {
737 
738  std::array< PositionsInQuadrant, 4 > positions;
739 
740  // three-ring layout
741  if ( m_geomVersion == 1 ) {
742  // the 1st disk
744  reorderRows( &d0q0front );
746  reorderRows( &d0q0back );
747 
748  // the 2nd disk is the same as the 1st, but mirrored
749  PositionsInQuadrant d1q0front = mirrorModulesInQuadrant( d0q0back );
750  PositionsInQuadrant d1q0back = mirrorModulesInQuadrant( d0q0front );
751 
752  positions[ 0 ] = std::move(d0q0front); // front-side module positions
753  positions[ 1 ] = std::move(d0q0back); // back-side module positions
754  positions[ 2 ] = std::move(d1q0front); // front-side module positions
755  positions[ 3 ] = std::move(d1q0back); // back-side module positions
756 
757  } else {
758  nRows = 18; // note 21-18 = 3 elements with positions of modules in rows are left empty
759  positions[0] = positions[2] = prepareQuadrantsFromRows(0, nRows ); // front-side module positions
760  positions[1] = positions[3] = prepareQuadrantsFromRows(1, nRows ); // back-side module positions
761  }
762  return positions;
763 }
764 
765 // careful m_geomVersion control layout implicitly
766 // backward compatibility to pre-TDR two-ring layouts
767 // 3-ring layout differ from 2-ring here.
768 std::string HGTD_DetectorFactory::formModuleName( int layer, int quadrant, unsigned int maxrows, int row, int mod,
769  const ModulePosition& module,
770  double& myx, double& myy, double& myrot, int& phi, int& eta ) {
771 
772  std::string module_string = "";
773 
774  double x = module.x;
775  double y = module.y;
776  double myphi = atan(y/x);
777  double radius = std::sqrt(x*x+y*y);
778 
779  myx = radius*cos( quadrant*M_PI*0.5 + myphi );
780  myy = radius*sin( quadrant*M_PI*0.5 + myphi );
781 
782  // three-ring layout
783  if ( m_geomVersion == 1 ) {
784  myrot = module.phiRotation;
785  phi = quadrant*21 + row + 1; // quadrant is absent ( hidden into row ) in HGTD-Identifier
786  eta = mod + 1;
787  //module_string = "_R" + std::to_string(phi) + "_M" + std::to_string(eta); //This was the previous string, but doesn't match expectations of HGTDSensorSD
788  module_string = "_layer_" + std::to_string(layer) + "_" + std::to_string(phi) + "_" + std::to_string(eta);
789  }
790  // two-ring layout
791  else {
792  double rot = module.flipped ? 90. : 0.;
793  int myrow = module.row;
794  double moduleRotation = 0;
795  if ( layer > 1 ) {
796  myx = -myx;
797  // need to rotate 180 degrees some modules in q0 and q2
798  if ( quadrant%2 == 0 && myrow <= 15) moduleRotation = 180.;
799  else if (quadrant%2 == 1 && myrow > 15) moduleRotation = 180.;
800  }
801  eta = ( quadrant*maxrows ) + myrow;
802  phi = module.el_in_row;
803  myrot = moduleRotation + rot;
804  module_string = "_layer_" + std::to_string(layer) + "_" + std::to_string(phi) + "_" + std::to_string(eta);
805  }
806 
807  return module_string;
808 }
809 
810 // calculate the positions of modules in a quadrant, taking care of separate schemes for two- and three-ring layouts
812 
813  PositionsInQuadrant rowsInQuad;
814  bool isBackside = (layer % 2);
815  // three-ring layout
816  if ( m_geomVersion == 1 ) {
817  for (size_t row = 0; row <= maxRow; row++) {
818  if ( row == 13 ) continue; // element #21 is tried since one row is skipped
819  std::vector<ModulePosition> rowModulePositions = prepareModulePositionsInRowThreeRing( row, isBackside );
820  rowsInQuad[ row > 13 ? row - 1 : row ] = std::move(rowModulePositions);
821  }
822  }
823  // two-ring layout
824  else {
825  for (size_t row = 0; row < maxRow; row++) {
826  std::vector<ModulePosition> rowModulePositions = prepareModulePositionsInRowTwoRing(row, isBackside);
827  rowsInQuad[ row ] = std::move(rowModulePositions);
828  }
829  }
830  return rowsInQuad;
831 }
832 
834  PositionsInQuadrant rowsInQuad;
835  for (size_t row = 0; row < inquad.size(); row ++ ) {
836  std::vector<ModulePosition> modulePositions = inquad[ row ];
837  for ( size_t mod = 0; mod < modulePositions.size(); mod++ ) {
838  ModulePosition old = modulePositions[mod];
839  ModulePosition mirror = old;
840  mirror.x = old.y;
841  mirror.y = old.x;
842  mirror.phiRotation = ( old.phiRotation == 0. ? 90. : 0. );
843  modulePositions[mod] = mirror;
844  }
845  // keeping the order defined in HGTD_DetectorFactory::reorderRows
846  rowsInQuad[ inquad.size() - row - 1 ] = std::move(modulePositions);
847  }
848  return rowsInQuad;
849 }
850 
851 // calculate module positions for the three-ring layout, updated to agree with post-TDR developments
852 std::vector< ModulePosition > HGTD_DetectorFactory::prepareModulePositionsInRowThreeRing( int row, int back ) {
853 
854  // below parameters should be collected into xml or RDB
855  int index_XYcoord_change = 14;
856 
857  // height is the short edge of module, width is the longer edge
858  float halfWidth = .5*40., halfHeight = .5*21.8; // bare module
859  float midR = 230., midR2 = 470.5, maxRcut = 660., maxOuterR = 670.;
860  // special tweak needed to avoid overlapping holes on front and back
861  if (row == 21 and back==1) {
862  midR2 = 510.;
863  }
864  float readoutRowSpace = 1.0;
865  bool extrude = ( ( row == 6 || row == 18 ) && !back ) || // front side
866  ( ( row == 2 || row == 11 || row == 12 || row == 17 ) && back ); // back side
867 
868  // instead of attempting to re-calculate the leading module per row, just pick up from dataBase,
869  // numbers here taken from spreadsheet at https://cernbox.cern.ch/index.php/s/PPXEWSBnBjwI7UU
870  std::array< float, 22 > ModStarting = { 122., 122.7, 89.85, 123.5, 175.4, 257.4, 287.5, 298.4, 287.5, 304.5, 287.5, 304.5, 287.5, 0.0, 299.7,
871  130., 114.7, 131.45, 164.45, 216.35, 205.45, 257.35 };
872 
873  std::array< float, 22 > ModStartBack = { 130., 114.7, 97.85, 131.5, 164.5, 246.5, 298.4, 287.5, 298.4, 287.5, 304.5, 287.5, 304.5, 0.0, 287.5,
874  122., 122.7, 123.45, 172.45, 205.45, 216.35, 246.45 };
875  /* row == 13 will be skipped from outside, and, since row == 15 XY flip take place. */
876 
877  // this is a bit hacky for this layout, a db-based solution will help in the future
878  int useCorner = 0;
879  if ( ( ( row == 1 || row == 5 || row == 15 || row == 19 ) && ! back ) || // front side
880  ( ( row == 0 || row == 8 || row == 16 || row == 18 || row == 21 ) && back ) // back side
881  ) useCorner = 1;
882  if ( row == 17 ) useCorner = 2;
883  // in some exceptional cases the spacing will be smaller even though the module crossed the ring boundary
884  float backshift = 6.;
885 
886  // the new layout tune makes small adjustments (usually 2~3 mm) for the last modules of some rows.
887  // even though most of element is zero for most of modules, we store these adjustments in a 2D array for now
888  float tailModCorrection[ 22 ][ 19 ];
889  for ( int r = 0; r < 22; r ++ )
890  for ( int m = 0; m < 19; m ++ ) tailModCorrection[r][m] = 0.;
891  tailModCorrection[11][4] = tailModCorrection[12][2] = 10.;
892 
893  // TDR layout: spaceSmallR = 5.5 , spaceMediumR = 8.4 , spaceLargeR = 14.5
894  float spaceSmallR = 3.7 , spaceMediumR = 6.6, spaceLargeR = 12.7; // updated spacings from post-TDR developments
895 
896  float backsideSmallR = spaceSmallR;
897  float backsideMediumR = spaceMediumR;
898  float backsideLargeR = spaceLargeR;
899 
900  float extendedWidth = readoutRowSpace + 2.*halfWidth;
901 
902  float posRadius = 0.;
903  float posOfLastPlacedModule = 0.; // start with dummy position
904  int moduleCounter = 0;
905  std::vector< ModulePosition > rowModulePositions;
906 
907  float effectiveRow = row;
908  // note the flipping of effectiveRow, it is the cause of XY flipping in later occurrance
909  if ( row == index_XYcoord_change ) effectiveRow = 13;
910  if ( row > index_XYcoord_change ) effectiveRow -= ( index_XYcoord_change + 1 );
911 
912  // x coordinate for vertical rows
913  float rowCentPos = 0.5*extendedWidth*( 2*effectiveRow + 1 );
914 
915  if ( extrude ) maxRcut = maxOuterR;
916  while ( posRadius < maxRcut ) {
917  // horizontal rows need care (restart from other edge of quadrant), this variable helps get the inner radius right
918  // y coordinate for vertical rows, then x coordinate for modules
919  float modPos_row = -999.;
920 
921  // for the first module in each row, take the starting position from the arrays created earlier from the spreadsheet
922  if ( moduleCounter == 0 ) { // leading module per row
923  modPos_row = ( back ? ModStartBack[row] : ModStarting[row] );
924  modPos_row += halfHeight;
925  }
926  // the rest of the modules follow sequential, radius-dependent placement rules
927  else {
928  float prevX = rowModulePositions[ moduleCounter - 1 ].x;
929  float prevY = rowModulePositions[ moduleCounter - 1 ].y;
930  float spacing = back ? backsideSmallR : spaceSmallR;
931 
932  // increase the spacing by the ring it will fallin
933  float ringCrossRcorner = std::sqrt( ( prevY + halfHeight)*( prevY + halfHeight) +
934  ( prevX + halfWidth )*( prevX + halfWidth ) );
935  float ringCrossRcenter = std::sqrt( prevY*prevY + prevX*prevX );
936 
937  bool tuned_center = ( row == 3 && ( moduleCounter == 3 && !back ) ) || // front, row 3
938  ( row == 20 && moduleCounter == 8 && !back ) || // front, row 20
939  ( row == 21 && moduleCounter == 6 && back ); // back, row 21
940  if ( useCorner == 2 ) {
941  if ( ( moduleCounter == 3 && ! back ) || ( ( moduleCounter == 3 || moduleCounter == 4 ) && back ) ) {
942  ringCrossRcenter -= backshift;
943  if ( ringCrossRcenter > midR && ringCrossRcenter <= midR2 ) spacing = back ? backsideMediumR : spaceMediumR;
944  if ( ringCrossRcenter > midR2 ) spacing = back ? backsideLargeR : spaceLargeR;
945  }
946  else {
947  if ( ringCrossRcorner > midR && ringCrossRcorner <= midR2 ) spacing = back ? backsideMediumR : spaceMediumR;
948  if ( ringCrossRcorner > midR2 ) spacing = back ? backsideLargeR : spaceLargeR;
949  }
950  }
951  else if ( useCorner == 1 ) {
952  if ( ringCrossRcorner > midR && ringCrossRcorner <= midR2 ) spacing = back ? backsideMediumR : spaceMediumR;
953  if ( ringCrossRcorner > midR2 ) spacing = back ? backsideLargeR : spaceLargeR;
954  }
955  else {
956  if ( tuned_center ) ringCrossRcenter -= backshift;
957  if ( ringCrossRcenter > midR && ringCrossRcenter <= midR2 ) spacing = back ? backsideMediumR : spaceMediumR;
958  if ( ringCrossRcenter > midR2 ) spacing = back ? backsideLargeR : spaceLargeR;
959  }
960 
961  modPos_row = posOfLastPlacedModule + 2.*halfHeight + spacing;
962 
963  if ( back && moduleCounter < 19) modPos_row -= tailModCorrection[ row ][ moduleCounter ];
964 
965  } // endif non-leading module
966 
967  // check and limit the length of the row
968  posRadius = std::sqrt( ( rowCentPos + halfWidth )*( rowCentPos + halfWidth ) +
969  ( modPos_row + halfHeight)*( modPos_row + halfHeight ) );
970  if ( posRadius > maxRcut ) {
971  ATH_MSG_DEBUG(" row " << row <<" finished with " << moduleCounter <<" modules ");
972  break;
973  }
974 
975  // the X and Y coordinates need to be flipped if this row is horizontal,
976  // needed only for backwards compatibility for two-ring layout
977  ModulePosition modu = { modPos_row, rowCentPos, 0., false, row, moduleCounter };
978  ModulePosition moduFlipped = { rowCentPos, modPos_row, 90., true, row, moduleCounter };
979 
980  // eventually arrived at a module to append into this row
981  if ( row > index_XYcoord_change ) rowModulePositions.push_back( modu );
982  else rowModulePositions.push_back( moduFlipped );
983 
984  // the spreadsheet gave the center of bottom edge of a module, so an adjustment by halfHeight is needed
985  if ( m_outputIdfr ) ATH_MSG_DEBUG( " Row " << ( row <= index_XYcoord_change ? effectiveRow + 1 : 36 - row )
986  << " Module " << moduleCounter + 1 <<" at (x,y) : "
987  << ( row > index_XYcoord_change ? rowModulePositions.back().x - halfHeight : rowModulePositions.back().x ) << ", "
988  << ( row > index_XYcoord_change ? rowModulePositions.back().y : rowModulePositions.back().y - halfHeight ) );
989 
990  posOfLastPlacedModule = modPos_row;
991  moduleCounter ++;
992  } // endof while loop
993 
994  if ( m_outputIdfr ) std::cout << "Total #Module " << rowModulePositions.size() <<" at original row " << row << std::endl;
995 
996  return rowModulePositions;
997 }
998 
999 // adjust row ordering to adhere to a convention in upper right quadrant of front :
1000 // 0 is first/bottom of many horizontal laid module along X-coord ( Y is almost zero )
1001 // increasing as they're stacked upwards ( anticlockwise ), the upmost horizontal is 6
1002 // then the outermost ( right-most ) vertical is 7, increase as they are laid to left
1003 // 20 is the last ( left ) adhereing to Y-coord ( X is almost zero )
1004 //
1006 
1007  PositionsInQuadrant tmpQuadrant;
1008  int xchng = 0;
1009  unsigned int numrow = quadrant->size();
1010  for ( unsigned int r = 0; r < numrow; r ++ ) {
1011  unsigned int idx = r > 13 ? 13 + numrow - r : r;
1012  ATH_MSG_DEBUG( " original row " << ( r <= 12 ? r : r + 1 ) <<" new row " << idx + 1
1013  << " : "<< numrow );
1014  tmpQuadrant[ idx ] = quadrant->at( r );
1015  if ( idx != r ) xchng++;
1016  }
1017  // refill the quadrant
1018  for ( unsigned int r = 0; r < numrow; r++ )
1019  quadrant->at( r ) = tmpQuadrant[ numrow - 1 - r ];
1020 
1021  return xchng;
1022 }
1023 
1024 void HGTD_DetectorFactory::mirrorPositionsAroundYaxis(std::array< PositionsInQuadrant, 4 >& arr) {
1025  for (auto& layer : arr) {
1026  for (auto& row : layer) {
1027  for (auto& module : row) {
1028  module.x = -module.x;
1029  }
1030  }
1031  }
1032 }
1033 
1034 
1036 
1037  double phiPitch = 1.3; // mm
1038  double etaPitch = 1.3; // mm
1039 
1040  // for each module there are two ASICs connected, need further confirmation for below specifications
1041  // the "collumns" along module short edge align to a direction just following the EndOfCollumn(EoC) of each ASIC.
1042  int circuitsPerColumn = 1;
1043  int circuitsPerRow = 2; // along the long edge of module, tentatively following IBL descriptin
1044 
1045  // each ASIC just cover half ( 15*15 pixels ) of a module
1046  int cellColumnsPerCircuit = 15;
1047  int cellRowsPerCircuit = 15; // along module FULL length there are 2*15 rows
1048 
1049  int diodeColumnsPerCircuit = cellColumnsPerCircuit;
1050  int diodeRowsPerCircuit = cellRowsPerCircuit;
1051 
1052  std::shared_ptr<const PixelDiodeMatrix> normalCell = InDetDD::PixelDiodeMatrix::construct(phiPitch, etaPitch);
1053  std::shared_ptr<const PixelDiodeMatrix> singleRow = InDetDD::PixelDiodeMatrix::construct(InDetDD::PixelDiodeMatrix::phiDir, 0,
1054  std::move(normalCell), diodeColumnsPerCircuit, 0);
1055  std::shared_ptr<const PixelDiodeMatrix> fullMatrix = InDetDD::PixelDiodeMatrix::construct(InDetDD::PixelDiodeMatrix::etaDir, 0,
1056  std::move(singleRow), 2*diodeRowsPerCircuit, 0); // note 30 = 2*15 rows adopted
1057 
1059 
1061  circuitsPerColumn, circuitsPerRow,
1062  cellColumnsPerCircuit, cellRowsPerCircuit,
1063  diodeColumnsPerCircuit, diodeRowsPerCircuit,
1064  std::move(fullMatrix),
1065  InDetDD::CarrierType::electrons, 1, yDirection );
1066 
1067  return design;
1068 }
1069 
1071  return m_detectorManager;
1072 }
1073 
1074 // backwards compatibility two-ring layout used for TDR studies
1075 std::vector<ModulePosition> HGTD_DetectorFactory::prepareModulePositionsInRowTwoRing(int row, bool back) {
1076 
1077  unsigned int module = 0;
1078  std::vector<ModulePosition> modulePositions;
1079  double posOfLastPlacedModule = 0.;
1080 
1081  while (true) {
1082  //ATH_MSG_INFO) << "Will now place module " << module );
1083  // horizontal rows need care (restart from other edge of quadrant), this variable helps get the inner radius right
1084  // in quadrant 0 - ie top right quadrant
1085  // row 0 = bottom horizontal row. numbering grows upwards and counterclockwise; row 17=leftmost vertical row
1086  // rowForInnerRadius = 0-1 for vertical rows too
1087  int rowForInnerRadius = row; // because row 16-17 are equivalent to 0-1 regarding module placement
1088  if (row == 17) rowForInnerRadius = 0;
1089  if (row == 16) rowForInnerRadius = 1;
1090 
1091  // params needed frequently below
1092  double moduleWidth = m_boxVolPars["HGTDModule0"].yHalf*2;
1093  double moduleHeight = m_boxVolPars["HGTDModule0"].xHalf*2;
1094  double rInner = m_cylVolPars["HGTD::ModuleLayer0"].rMin;
1095  double rMid = m_hgtdPars.rMid;
1096  double rOuter = m_hgtdPars.rOuter;
1097  double rowSpaceSide = m_hgtdPars.rowSpaceSide;
1098 
1099  // x coordinate for vertical rows
1100  double rowCenterPos = (moduleWidth + rowSpaceSide)*(rowForInnerRadius + 0.5);
1101  // y coordinate for vertical rows
1102  double modulePosAlongRow = -99.; // mock value for now
1103  // for the first module, pick the right starting point
1104  if (modulePositions.empty()) {
1105  // start at inner radius and include any offset for backside.
1106  if (rowForInnerRadius < 3) {
1107  modulePosAlongRow = std::sqrt( pow(rInner, 2) - pow((moduleWidth + rowSpaceSide)*rowForInnerRadius, 2) )
1108  + back*m_hgtdPars.rowBacksideInnerShift + moduleHeight/2;
1109  }
1110  else { // later modules start at 2*moduleWidth, with offset for the backside
1111  double backSpacing = m_hgtdPars.rowBacksideInnerShift;
1112  if (back && (rowCenterPos - moduleWidth/2 > rMid)) {
1113  backSpacing = m_hgtdPars.rowBacksideOuterShift;
1114  }
1115  modulePosAlongRow = 2*(moduleWidth + rowSpaceSide) + moduleHeight/2 + back*backSpacing;
1116  }
1117  }
1118  // the rest of the modules follow sequential, radius-dependent placement rules
1119  else {
1120  ModulePosition prev = modulePositions.back();
1121  double spacing = m_hgtdPars.moduleSpaceInner;
1122  // if the previous module was completely outside rMid, increase the spacing
1123  // (+1 mm is a needed shift for full coverage - could need tweaking if layout parameters change!)
1124  float innermostCornerR = std::sqrt( pow(prev.y - moduleHeight/2, 2) + pow(prev.x - moduleWidth/2, 2) ) + 1.;
1125  if (innermostCornerR > rMid) {
1126  spacing = m_hgtdPars.moduleSpaceOuter;
1127  }
1128  // for the back the large spacing starts as soon as the space would entirely be outside R = 320 mm
1129  if (back) {
1130  double startOfSpaceAlongRow = std::sqrt( pow(prev.y + moduleHeight/2, 2) + pow(prev.x - moduleWidth/2, 2) ) - 2;
1131  if (startOfSpaceAlongRow > rMid) {
1132  spacing = m_hgtdPars.moduleSpaceOuter;
1133  }
1134  }
1135  // correction to the first two spaces on the front side, compensating for the 2 mm introduced at beginning of a row
1136  if (!back && rowForInnerRadius < 8 && module < 3) {
1137  spacing -= 1.; // should result in 3 mm instead of 4 mm for innermost spaces on rows starting at R = 120
1138  }
1139  // squeeze in a few more modules at the end of some rows
1140  double maxRcut = rOuter+20;
1141  if(row == 8 || row == 9 || row == 10) {
1142  maxRcut = 661;
1143  if(row == 8 && module > 12) spacing -= 4;
1144  }
1145  else if ( row == 11 && module > 9) {
1146  maxRcut = 662;
1147  spacing -= 6;
1148  }
1149  else if (row == 12 && back) {
1150  maxRcut = 665;
1151  }
1152  else if(row == 13 && module > 5) {
1153  maxRcut = 666;
1154  if (!back && module > 6 ) spacing -= 8.5;
1155  else if (back && module > 5) spacing -= 2;
1156  }
1157  else if (row == 14 && module > 3) {
1158  maxRcut = 665;
1159  spacing -= 5;
1160  }
1161  else if (row == 15) {
1162  maxRcut = 669;
1163  spacing -= 5.5;
1164  }
1165  modulePosAlongRow = posOfLastPlacedModule + moduleHeight + spacing;
1166  // stop if the next module will extend outside the max allowed radius
1167  // HC max radius is 665
1168  if ( std::sqrt( pow(rowCenterPos + moduleWidth/2, 2) + pow(modulePosAlongRow + moduleHeight/2, 2) ) > maxRcut) {
1169  break;
1170  }
1171  }
1172  ModulePosition m = {rowCenterPos, modulePosAlongRow, 0, true, row, (int)module};
1173  modulePositions.push_back(m);
1174  posOfLastPlacedModule = modulePosAlongRow;
1175  module += 1;
1176  } // end of loop over modules
1177 
1178  // finally, flip x and y for all modules if this row is horizontal
1179  if (row < 16) {
1180  // ATH_MSG_INFO) << "Flipping x and y for modules in row " << row );
1181  for (size_t i=0; i < modulePositions.size(); i++) {
1182  ModulePosition old = modulePositions[i];
1183  ModulePosition rotated = old;
1184  rotated.x = old.y;
1185  rotated.y = old.x;
1186  rotated.flipped = !old.flipped;
1187  rotated.row = old.row;
1188  rotated.el_in_row = old.el_in_row;
1189  modulePositions[i] = rotated;
1190  }
1191  }
1192 
1193  ATH_MSG_DEBUG( "row = " << row );
1194  for(size_t i=0; i < modulePositions.size(); i++) {
1195  ATH_MSG_DEBUG( "Module " << i << " at (x,y) = (" << modulePositions[i].x << "," << modulePositions[i].y << ")" );
1196  }
1197 
1198  return modulePositions;
1199 }
plotting.yearwise_luminosity_vs_mu.comp
comp
Definition: yearwise_luminosity_vs_mu.py:23
query_example.row
row
Definition: query_example.py:24
beamspotman.r
def r
Definition: beamspotman.py:676
HGTD_GeoModelAthenaComps
Class to hold various Athena components.
Definition: HGTD_GeoModelAthenaComps.h:14
GeoCylVolParams::rMin
double rMin
Definition: HGTD_DetectorFactory.h:55
InDetDD::DetectorFactoryBase
Definition: InDetDetectorFactoryBase.h:20
HGTD_DetectorFactory::reorderRows
int reorderRows(PositionsInQuadrant *quadrant)
Definition: HGTD_DetectorFactory.cxx:1005
GeoCylVolParams::name
std::string name
Definition: HGTD_DetectorFactory.h:54
HGTD_DetectorFactory::build
GeoVPhysVol * build(const GeoLogVol *logicalEnvelope, bool bPos)
Definition: HGTD_DetectorFactory.cxx:297
python.SystemOfUnits.m
int m
Definition: SystemOfUnits.py:91
phi
Scalar phi() const
phi method
Definition: AmgMatrixBasePlugin.h:67
CondAttrListCollection.h
This file defines the class for a collection of AttributeLists where each one is associated with a ch...
AthCheckMacros.h
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
HGTD_ID::wafer_hash
IdentifierHash wafer_hash(Identifier wafer_id) const
wafer hash from id
Definition: HGTD_ID.h:404
AthMsgStreamMacros.h
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
HgtdGeoParams::disk2Rotation
double disk2Rotation
Definition: HGTD_DetectorFactory.h:34
HGTD_DetectorFactory::m_athComps
HGTD_GeoModelAthenaComps * m_athComps
Definition: HGTD_DetectorFactory.h:116
GeoCylVolParams
Definition: HGTD_DetectorFactory.h:53
eta
Scalar eta() const
pseudorapidity method
Definition: AmgMatrixBasePlugin.h:83
HGTD_DetectorFactory::mirrorModulesInQuadrant
PositionsInQuadrant mirrorModulesInQuadrant(const PositionsInQuadrant &)
Definition: HGTD_DetectorFactory.cxx:833
ModulePosition::phiRotation
double phiRotation
Definition: HGTD_DetectorFactory.h:46
InDetDD::DetectorDesign::yAxis
@ yAxis
Definition: DetectorDesign.h:60
StoredMaterialManager::getElement
virtual const GeoElement * getElement(const std::string &name)=0
cm3
#define cm3
InDetDD::HGTD_DetectorElement
Definition: HGTD_DetectorElement.h:40
HGTD_DetectorFactory::m_cylVolPars
std::map< std::string, GeoCylVolParams > m_cylVolPars
Definition: HGTD_DetectorFactory.h:124
M_PI
#define M_PI
Definition: ActiveFraction.h:11
InDetDD::PixelDiodeMatrix::construct
static std::shared_ptr< const PixelDiodeMatrix > construct(double phiWidth, double etaWidth)
Construct method for just a single cell.
Definition: PixelDiodeMatrix.cxx:14
deg
#define deg
Definition: SbPolyhedron.cxx:17
StoredAlignX.h
HgtdGeoParams::rowSpaceSide
double rowSpaceSide
Definition: HGTD_DetectorFactory.h:35
HGTD_DetectorFactory::HGTD_DetectorFactory
HGTD_DetectorFactory(HGTD_GeoModelAthenaComps *athenaComps)
Definition: HGTD_DetectorFactory.cxx:59
InDetDD::DetectorDesign::Axis
Axis
Definition: DetectorDesign.h:59
python.SystemOfUnits.gram
int gram
Definition: SystemOfUnits.py:165
PositionsInQuadrant
std::array< std::vector< ModulePosition >, 21 > PositionsInQuadrant
Definition: HGTD_DetectorFactory.h:71
drawFromPickle.cos
cos
Definition: drawFromPickle.py:36
HGTD_DetectorFactory::m_geomVersion
int m_geomVersion
Definition: HGTD_DetectorFactory.h:119
HgtdGeoParams::moduleSpaceInner
double moduleSpaceInner
Definition: HGTD_DetectorFactory.h:38
HGTD_GeoModelAthenaComps::getIdHelper
const HGTD_ID * getIdHelper() const
Definition: HGTD_GeoModelAthenaComps.cxx:19
HgtdGeoParams::flexSheetSpacing
double flexSheetSpacing
Definition: HGTD_DetectorFactory.h:40
x
#define x
HGTD_DetectorFactory::setPrintIdentifierDict
void setPrintIdentifierDict(bool)
Definition: HGTD_DetectorFactory.cxx:83
HGTD_DetectorManager.h
HGTD_DetectorFactory::prepareLayersFromQuadrants
std::array< PositionsInQuadrant, 4 > prepareLayersFromQuadrants(unsigned int)
Definition: HGTD_DetectorFactory.cxx:736
drawFromPickle.atan
atan
Definition: drawFromPickle.py:36
AthenaPoolTestRead.sc
sc
Definition: AthenaPoolTestRead.py:27
HGTD_ID::wafer_id
Identifier wafer_id(int endcap, int layer, int phi_module, int eta_module) const
For a single crystal.
Definition: HGTD_ID.h:287
DeMoUpdate.reverse
reverse
Definition: DeMoUpdate.py:563
InDetDD::PixelDiodeMatrix::phiDir
@ phiDir
Definition: PixelDiodeMatrix.h:97
TRT::Hit::side
@ side
Definition: HitInfo.h:83
HGTD_DetectorFactory::m_commonItems
std::unique_ptr< const InDetDD::SiCommonItems > m_commonItems
Definition: HGTD_DetectorFactory.h:128
python.PyAthena.module
module
Definition: PyAthena.py:131
HGTD_DetectorFactory::buildEndcapLogicalVolume
GeoLogVol * buildEndcapLogicalVolume(bool isPositiveSide)
Definition: HGTD_DetectorFactory.cxx:282
ModulePosition
Definition: HGTD_DetectorFactory.h:43
HgtdGeoParams::moduleSpaceOuter
double moduleSpaceOuter
Definition: HGTD_DetectorFactory.h:39
IRDBAccessSvc.h
Definition of the abstract IRDBAccessSvc interface.
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
HGTD_DetectorFactory::m_outputIdfr
bool m_outputIdfr
Definition: HGTD_DetectorFactory.h:122
maskDeadModules.mod
mod
Definition: maskDeadModules.py:36
InDetDD::DetectorFactoryBase::detStore
StoreGateSvc * detStore()
Definition: InDetDetectorFactoryBase.h:27
HGTD_GeoModelAthenaComps.h
ModulePosition::y
double y
Definition: HGTD_DetectorFactory.h:45
HGTD_DetectorFactory::m_detectorManager
HGTD_DetectorManager * m_detectorManager
Definition: HGTD_DetectorFactory.h:115
lumiFormat.i
int i
Definition: lumiFormat.py:85
GeoCylVolParams::rMax
double rMax
Definition: HGTD_DetectorFactory.h:56
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
SiCommonItems.h
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
AlignableTransformContainer.h
TRT::Hit::layer
@ layer
Definition: HitInfo.h:79
HGTD_DetectorElement.h
Amg::Transform3D
Eigen::Affine3d Transform3D
Definition: GeoPrimitives.h:46
HGTD_DetectorManager::addTreeTop
void addTreeTop(PVConstLink treeTop)
Add a Tree top:
Definition: HGTD_DetectorManager.cxx:53
StoredMaterialManager::addMaterial
virtual void addMaterial(const std::string &space, GeoMaterial *material)=0
HGTD_DetectorFactory::prepareModulePositionsInRowTwoRing
std::vector< ModulePosition > prepareModulePositionsInRowTwoRing(int row, bool back=false)
Definition: HGTD_DetectorFactory.cxx:1075
HGTD_ID
Definition: HGTD_ID.h:47
ModulePosition::flipped
bool flipped
Definition: HGTD_DetectorFactory.h:48
HGTD_DetectorFactory::m_materialMgr
StoredMaterialManager * m_materialMgr
Definition: HGTD_DetectorFactory.h:117
ModulePosition::x
double x
Definition: HGTD_DetectorFactory.h:44
print
void print(char *figname, TCanvas *c1)
Definition: TRTCalib_StrawStatusPlots.cxx:25
GeoCylVolParams::zHalf
double zHalf
Definition: HGTD_DetectorFactory.h:57
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
ActsTrk::to_string
std::string to_string(const DetectorType &type)
Definition: GeometryDefs.h:34
StoredMaterialManager.h
HGTD_DetectorManager::addDetectorElement
void addDetectorElement(InDetDD::HGTD_DetectorElement *element)
Add elememts.
Definition: HGTD_DetectorManager.cxx:94
HGTD_ID.h
HgtdGeoParams::rMid
double rMid
Definition: HGTD_DetectorFactory.h:31
HGTD_DetectorFactory::createHgtdDesign
InDetDD::HGTD_ModuleDesign * createHgtdDesign(double thickness)
Definition: HGTD_DetectorFactory.cxx:1035
DecodeVersionKey.h
ParticleGun_SamplingFraction.radius
radius
Definition: ParticleGun_SamplingFraction.py:96
HGTD_DetectorFactory::m_hgtdPars
HgtdGeoParams m_hgtdPars
Definition: HGTD_DetectorFactory.h:126
HGTD_DetectorFactory::prepareModulePositionsInRowThreeRing
std::vector< ModulePosition > prepareModulePositionsInRowThreeRing(int row, int back=0)
Definition: HGTD_DetectorFactory.cxx:852
HGTD_DetectorFactory::~HGTD_DetectorFactory
virtual ~HGTD_DetectorFactory()
Definition: HGTD_DetectorFactory.cxx:79
GeoCylVolParams::material
std::string material
Definition: HGTD_DetectorFactory.h:59
HgtdGeoParams::disk1Rotation
double disk1Rotation
Definition: HGTD_DetectorFactory.h:33
GeoCylVolParams::zOffsetLocal
double zOffsetLocal
Definition: HGTD_DetectorFactory.h:58
ModulePosition::row
int row
Definition: HGTD_DetectorFactory.h:49
python.PyAthena.v
v
Definition: PyAthena.py:154
PixelDiodeMatrix.h
IRDBRecord.h
Definition of the abstract IRDBRecord interface.
HGTD_DetectorFactory::m_boxVolPars
std::map< std::string, GeoBoxVolParams > m_boxVolPars
Definition: HGTD_DetectorFactory.h:125
y
#define y
HgtdGeoParams::rowBacksideInnerShift
double rowBacksideInnerShift
Definition: HGTD_DetectorFactory.h:36
CSV_InDetExporter.old
old
Definition: CSV_InDetExporter.py:145
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
HGTD_ModuleDesign.h
InDetDD
Message Stream Member.
Definition: FakeTrackBuilder.h:8
HGTD_DetectorManager::setCommonItems
void setCommonItems(std::unique_ptr< const InDetDD::SiCommonItems > &&commonItems)
Set SiCommonItems.
Definition: HGTD_DetectorManager.cxx:129
HGTD_DetectorFactory.h
HGTD_DetectorFactory::getDetectorManager
virtual const HGTD_DetectorManager * getDetectorManager() const override
Definition: HGTD_DetectorFactory.cxx:1070
HGTD_DetectorFactory::initializeGeoParameters
void initializeGeoParameters()
Definition: HGTD_DetectorFactory.cxx:129
StoredMaterialManager::getMaterial
virtual const GeoMaterial * getMaterial(const std::string &name)=0
LArNewCalib_DelayDump_OFC_Cali.idx
idx
Definition: LArNewCalib_DelayDump_OFC_Cali.py:69
HGTD_DetectorFactory::formModuleName
std::string formModuleName(int layer, int quadrant, unsigned int maxrows, int row, int mod, const ModulePosition &module, double &myx, double &myy, double &myrot, int &phi, int &eta)
Definition: HGTD_DetectorFactory.cxx:768
HGTD_DetectorManager
Definition: HGTD_DetectorManager.h:33
HGTD_DetectorFactory::prepareQuadrantsFromRows
PositionsInQuadrant prepareQuadrantsFromRows(int layer, unsigned int maxRow)
Definition: HGTD_DetectorFactory.cxx:811
extractSporadic.q
list q
Definition: extractSporadic.py:98
InDetDD::HGTD_ModuleDesign
Definition: HGTD_ModuleDesign.h:43
CxxUtils::atoi
int atoi(std::string_view str)
Helper functions to unpack numbers decoded in string into integers and doubles The strings are requir...
Definition: Control/CxxUtils/Root/StringUtils.cxx:85
RPDUtils::nRows
unsigned constexpr int nRows
Definition: RPDUtils.h:24
drawFromPickle.sin
sin
Definition: drawFromPickle.py:36
IRDBRecordset.h
Definition of the abstract IRDBRecordset interface.
HGTD_DetectorFactory::create
virtual void create(GeoPhysVol *world) override
Definition: HGTD_DetectorFactory.cxx:88
IGeoModelSvc.h
HgtdGeoParams::rOuter
double rOuter
Definition: HGTD_DetectorFactory.h:32
pow
constexpr int pow(int base, int exp) noexcept
Definition: ap_fixedTest.cxx:15
ModulePosition::el_in_row
int el_in_row
Definition: HGTD_DetectorFactory.h:50
HgtdGeoParams::rowBacksideOuterShift
double rowBacksideOuterShift
Definition: HGTD_DetectorFactory.h:37
StoreGateSvc.h
python.compressB64.c
def c
Definition: compressB64.py:93
InDetDD::electrons
@ electrons
Definition: InDetDD_Defs.h:17
HGTD_DetectorFactory::mirrorPositionsAroundYaxis
void mirrorPositionsAroundYaxis(std::array< PositionsInQuadrant, 4 > &arr)
Definition: HGTD_DetectorFactory.cxx:1024
InDetDD::PixelDiodeMatrix::etaDir
@ etaDir
Definition: PixelDiodeMatrix.h:97
StoredPhysVol.h
Identifier
Definition: IdentifierFieldParser.cxx:14