ATLAS Offline Software
Loading...
Searching...
No Matches
PixelDetectorDC1DC2.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5// This file is basically a concatenation of all the *.cxx files.
6// This allows one to keep a stable copy of the DC2 version and
7// allow development of future versions.
8
10
17
19#include "GeoModelKernel/GeoAlignableTransform.h"
20#include "GeoModelKernel/GeoBox.h"
21#include "GeoModelKernel/GeoFullPhysVol.h"
22#include "GeoModelKernel/GeoIdentifierTag.h"
23#include "GeoModelKernel/GeoLogVol.h"
24#include "GeoModelKernel/GeoMaterial.h"
25#include "GeoModelKernel/GeoNameTag.h"
26#include "GeoModelKernel/GeoPhysVol.h"
27#include "GeoModelKernel/GeoTransform.h"
28#include "GeoModelKernel/GeoTube.h"
29#include "GeoModelKernel/GeoTubs.h"
30#include "GaudiKernel/PhysicalConstants.h"
33#include "Identifier/Identifier.h"
35#include "GaudiKernel/Bootstrap.h"
36#include "GaudiKernel/ISvcLocator.h"
37
40
41#include <memory>
42#include <vector>
43
44#include "PixelGeoUtils.h"
45
46using namespace PixelGeoDC2;
47
48
49//---------------------------------------------------//
50// //
51// GeoPixelBarrel //
52// //
53//---------------------------------------------------//
54
55
56GeoVPhysVol* GeoPixelBarrel::Build( ) {
57
58 //
59 // create the Barrel Mother volume
60 //
61 double rmin = m_gmt_mgr->PixelBarrelRMin();
62 double rmax = m_gmt_mgr->PixelBarrelRMax();
63 double halflength = m_gmt_mgr->PixelBarrelHalfLength();
64 const GeoMaterial* air = m_mat_mgr->getMaterial("std::Air");
65 const GeoTube* barrelTube = new GeoTube(rmin,rmax,halflength);
66 const GeoLogVol* barrelLog = new GeoLogVol("barrelLog",barrelTube,air);
67 GeoPhysVol* barrelPhys = new GeoPhysVol(barrelLog);
68
69 // Set numerology
70 m_DDmgr->numerology().setNumLayers(m_gmt_mgr->PixelBarrelNLayer());
71
72 //
73 // Build the layers inside
74 //
76 std::string lname[3];
77 lname[0] = "InnerLayer";
78 lname[1] = "CenterLayer";
79 lname[2] = "OuterLayer";
80 for(int ii = 0; ii < m_gmt_mgr->PixelBarrelNLayer(); ii++) {
81 //cout << "Layer" << ii << endl;
82 m_gmt_mgr->SetCurrentLD(ii);
83 if(m_gmt_mgr->isLDPresent()) {
84 GeoAlignableTransform * xform = new GeoAlignableTransform(GeoTrf::Transform3D::Identity());
85 GeoVPhysVol* layerphys = layer.Build();
86 GeoNameTag *tag = new GeoNameTag(lname[ii]);
87 barrelPhys->add(tag);
88 barrelPhys->add(new GeoIdentifierTag(ii));
89 barrelPhys->add(xform);
90 barrelPhys->add(layerphys);
91
92 // Store the transform (at level 1)
93 Identifier id = m_gmt_mgr->getIdHelper()->wafer_id(0,ii,0,0);
94 m_DDmgr->addAlignableTransform(1, id, xform, layerphys);
95 } else {
96 m_gmt_mgr->msg(MSG::DEBUG) << "Layer " << ii << " not built" << endmsg;
97 }
98 }
99 if(m_gmt_mgr->DoServices() ) {
100 //
101 // Add the services inside the barrel volume
102 //
103 GeoPixelServices brlsvc = GeoPixelServices(m_DDmgr, m_gmt_mgr, "/Pixel/PixelBarrel");
104 for(int ii =0; ii< brlsvc.NCylinders(); ii++) {
105 brlsvc.SetCylinder(ii);
106 GeoNameTag* tag = new GeoNameTag("Outside Barrel Service");
107 GeoTrf::Translate3D pos(0.,0.,brlsvc.ZPos() );
108 GeoTransform* xform = new GeoTransform(pos);
109 barrelPhys->add(tag);
110 barrelPhys->add(xform);
111 barrelPhys->add(brlsvc.Build() );
112 }
113 }
114 return barrelPhys;
115}
116
117//---------------------------------------------------//
118// //
119// GeoPixelCable //
120// //
121//---------------------------------------------------//
122
123
124
125GeoVPhysVol* GeoPixelCable::Build() {
126 //
127 // Dimensions
128 //
129 double length = this->Length();
130 double thickness = this->Thickness();
131 double width = m_gmt_mgr->PixelCableWidth();
132 const GeoMaterial* cable = m_mat_mgr->getMaterial("pix::Cable");
133 const GeoBox* cableBox = new GeoBox(thickness/2.,width/2.,length/2.);
134 std::string logName = std::string("cableLog")+std::to_string(m_moduleNumber);;
135 GeoLogVol* theCable = new GeoLogVol(logName,cableBox,cable);
136 GeoPhysVol* cablePhys = new GeoPhysVol(theCable);
137 return cablePhys;
138}
139
140
142 //
143 // The cable is running from the beginning of the module to which
144 // it is attached to the end of the ladder,
145 // zmax gives the end of the ladder and zmin is the begining of the module
146 // in absolute value, so the cable lenght is the difference b/w the two
147 // the TubeCables factory will have to position this cable in the correct
148 // side.
149 //
150 double zmax = m_gmt_mgr->PixelCableZMax();
151 double zmin = m_gmt_mgr->PixelCableZMin()+m_moduleNumber*m_gmt_mgr->PixelCableDeltaZ();
152 return zmax-zmin-m_epsilon;
153}
154
156 //
157 // This is calculated from the Gaudi::Units::rad length of the cables and their mass
158 // I have to go back on this later when I'll have defined a material
159 // manager, for the time being I get the thickness by atlsim, using dtree
160 // anf hardwire the numbers in the code...
161 // I have to come back on the thickness using the cables recipes
162 //
163 if(m_moduleNumber == 0) return 2.*0.0028412*Gaudi::Units::cm;
164 if(m_moduleNumber == 1) return 2.*0.0056795*Gaudi::Units::cm;
165 if(m_moduleNumber == 2) return 2.*0.0056830*Gaudi::Units::cm;
166 if(m_moduleNumber == 3) return 2.*0.0056763*Gaudi::Units::cm;
167 if(m_moduleNumber == 4) return 2.*0.0056752*Gaudi::Units::cm;
168 if(m_moduleNumber == 5) return 2.*0.0057058*Gaudi::Units::cm;
169 if(m_moduleNumber == 6) return 2.*0.0056818*Gaudi::Units::cm;
170
171 return 0.;
172
173}
174
175//---------------------------------------------------//
176// //
177// GeoPixelChip //
178// //
179//---------------------------------------------------//
180
181
182//
183// This class builds one Chip to be placed in one module
184//
185// The information on which layer to build is retrieved by the Geometry Manager
186//
187// Contained by: PixelModule_log
188//
189// Contains: nothing
190//
191
192GeoVPhysVol* GeoPixelChip::Build() {
193 //
194 // Dimensions
195 //
196 double length = m_gmt_mgr->PixelChipLength();
197 double thickness = m_gmt_mgr->PixelChipThickness();
198 double width = m_gmt_mgr->PixelChipWidth();
199 const GeoMaterial* chipMat = m_mat_mgr->getMaterial("pix::Chip");
200 std::string LogName = "chipBrlLog";
201 //
202 // In G3 is like this...
203 //
204 if(m_gmt_mgr->isEndcap() ) {
205 chipMat = m_mat_mgr->getMaterial("std::Silicon");
206 LogName = "chipECLog";
207 }
208
209 //std::cout << "DC1 chip thick" << thickness << std::endl;
210 const GeoBox* chipBox = new GeoBox(thickness/2.,width/2.,length/2.);
211 GeoLogVol* theChip = new GeoLogVol(LogName,chipBox,chipMat);
212 GeoPhysVol* chipPhys = new GeoPhysVol(theChip);
213 return chipPhys;
214}
215
216
217//---------------------------------------------------//
218// //
219// GeoPixelDisk //
220// //
221//---------------------------------------------------//
222
223
226 : GeoVPixelFactory (ddmgr, mgr)
227{
228
229 // Define the log volume in the constructor, so I do it only once.
230 //
231
232 //
233 // Dimensions from class methods.
234 //
235 double rmin = RMin();
236 double rmax = RMax();
237 double halflength = Thickness()*0.5;
238 const GeoMaterial* air = m_mat_mgr->getMaterial("std::Air");
239 const GeoTube* diskTube = new GeoTube(rmin,rmax,halflength);
240 m_theDisk = new GeoLogVol("diskLog",diskTube,air);
241}
242
243GeoVPhysVol* GeoPixelDisk::Build( ) {
244 //
245 // Define the Sensor to be used here, so it will be the same for all the disk
246 GeoPixelSiCrystal theSensor(m_DDmgr, m_gmt_mgr, false);
247 GeoFullPhysVol* diskPhys = new GeoFullPhysVol(m_theDisk);
248 //
249 // Place the disk sectors (on both sides):
250 //
251 GeoPixelSubDisk psd(m_DDmgr, m_gmt_mgr, theSensor);
252 double zpos = -m_gmt_mgr->PixelECSiDz1()/2.;
253 double angle = 360.*Gaudi::Units::deg/ (float) m_gmt_mgr->PixelECNSectors1();
254 GeoTrf::Translation3D pos(0.,0.,zpos);
255
256 // Set numerology
257 m_gmt_mgr->SetEta(0);
260
261 // Even modules
262 m_gmt_mgr->SetEta(0);
263 for (int ii = 0; ii < m_gmt_mgr->PixelECNSectors1(); ii++) {
264 m_gmt_mgr->SetPhi(ii);
265 GeoTrf::Transform3D rm = GeoTrf::RotateZ3D(ii*angle+angle/2.)*GeoTrf::RotateX3D(180.*Gaudi::Units::deg);
266 GeoAlignableTransform* xform = new GeoAlignableTransform(GeoTrf::Transform3D(pos*rm));
267 GeoVPhysVol * modulePhys = psd.Build();
268 GeoNameTag* tag = new GeoNameTag("DiskSector");
269 diskPhys->add(tag);
270 diskPhys->add(new GeoIdentifierTag(getPhiId() ) );
271 diskPhys->add(xform);
272 diskPhys->add(modulePhys);
273
274 // Now store the xform by identifier:
275 Identifier id = theSensor.getID();
276 m_DDmgr->addAlignableTransform(0,id,xform,modulePhys);
277 }
278
279 // Odd modules
280 m_gmt_mgr->SetEta(1);
281 zpos = m_gmt_mgr->PixelECSiDz2()/2.;
282 pos = GeoTrf::Translation3D(0.,0.,zpos);
283 for (int ii = 0; ii < m_gmt_mgr->PixelECNSectors1(); ii++) {
284 m_gmt_mgr->SetPhi(ii);
285 GeoTrf::RotateZ3D rm((ii+1)*angle);
286 GeoAlignableTransform* xform = new GeoAlignableTransform(GeoTrf::Transform3D(pos*rm));
287 GeoVPhysVol * modulePhys = psd.Build();
288 GeoNameTag* tag = new GeoNameTag("DiskSector");
289 diskPhys->add(tag);
290 diskPhys->add(new GeoIdentifierTag(getPhiId() ) );
291 diskPhys->add(xform);
292 diskPhys->add(modulePhys);
293
294 // Now store the xform by identifier:
295 Identifier id = theSensor.getID();
296 m_DDmgr->addAlignableTransform(0,id,xform,modulePhys);
297 }
298 //
299 // Place the supports for the disks:
300 //
301 GeoPixelDiskSupports pds (m_DDmgr, m_gmt_mgr);
302 for(int ii =0; ii< pds.NCylinders(); ii++) {
303 pds.SetCylinder(ii);
304 GeoTrf::Translate3D pos(0.,0.,pds.ZPos() );
305 GeoNameTag* tag = new GeoNameTag("DiskSupport");
306 GeoTransform* xform = new GeoTransform(pos);
307 diskPhys->add(tag);
308 diskPhys->add(xform);
309 diskPhys->add(pds.Build() );
310 }
311
312 return diskPhys;
313}
314
315double GeoPixelDisk::RMin() {
316 return m_gmt_mgr->PixelECCarbonRMin("Inner");
317}
318
319double GeoPixelDisk::RMax() {
320 return m_gmt_mgr->PixelECCarbonRMax("Outer");
321}
322
324 //
325 // This can be calculated as the minimum thickness possible
326 // as for the layers I use a number which is enough to contain
327 // the inner part of the detector.
328 //
329 // 7-1 I switch to the minimum thickness possible as the cables are right
330 // outside this volume.
331 //
332 // return 10*Gaudi::Units::mm;
333 double tck = 2*(m_gmt_mgr->PixelBoardThickness()
334 +std::max(m_gmt_mgr->PixelHybridThickness(),m_gmt_mgr->PixelChipThickness()));
335 tck += std::max(m_gmt_mgr->PixelECSiDz1(),m_gmt_mgr->PixelECSiDz2());
336 return tck;
337}
338
339
340//
341// This is to retrofit the convention in the pixelId
342// \which is coming from atlsim...
343//
345 int brl_ec=0;
346 int phimod;
347 if(m_gmt_mgr->isBarrel() ) brl_ec = 0;
348 if(m_gmt_mgr->isEndcap() ) brl_ec = 2*m_gmt_mgr->GetSide();
349 if(brl_ec == 2) {
350 phimod = m_gmt_mgr->Phi()*2 + m_gmt_mgr->Eta();
351 } else {
352 //
353 // The (eta) negative) endcap is more complicated, as there is an extra
354 // rotation of the endcap as a whole around Y
355 //
356 phimod = 48-m_gmt_mgr->Phi()*2-m_gmt_mgr->Eta()-2;
357 if (phimod == -1) phimod = 47;
358 }
359 return phimod;
360}
361
362
363//---------------------------------------------------//
364// //
365// GeoPixelDiskSupports //
366// //
367//---------------------------------------------------//
368
369
372 : GeoVPixelFactory (ddmgr, mgr)
373{
374 //
375 // Initialize the vectors
376 //
377 //
378 // zpos is not needed, but it's here just in case...
379 //
380 std::string ele[3] = {"Inner", "Central", "Outer"};
381 for (int ii =0; ii<3; ii++) {
382 double rmin = m_gmt_mgr->PixelECCarbonRMin(ele[ii]);
383 double rmax = m_gmt_mgr->PixelECCarbonRMax(ele[ii]);
384 double halflength = m_gmt_mgr->PixelECCarbonThickness(ele[ii])/2.;
385 double zpos = 0.;
386 std::string mat = m_gmt_mgr->PixelECCarbonMaterial(ele[ii]);
387 m_rmin.push_back(rmin);
388 m_rmax.push_back(rmax);
389 m_zpos.push_back(zpos);
390 m_halflength.push_back(halflength);
391 m_material.push_back(std::move(mat));
392 }
393}
394
395
396
397GeoVPhysVol* GeoPixelDiskSupports::Build( ) {
398 const GeoMaterial* supportMat = m_mat_mgr->getMaterial(m_material[m_nframe]);
399 //
400 // Dimensions: (m_nframe set with teh SetCylinder method)
401 //
402 double rmin = m_rmin[m_nframe];
403 double rmax = m_rmax[m_nframe];
404 double halflength = m_halflength[m_nframe];
405 const GeoTube* supportTube = new GeoTube(rmin,rmax,halflength);
406 std::string logName = std::string("diskSupLog")+std::to_string(m_nframe);
407 GeoLogVol* theSupport = new GeoLogVol(logName,supportTube,supportMat);
408 GeoPhysVol* supportPhys = new GeoPhysVol(theSupport);
409 return supportPhys;
410}
411
412
413//---------------------------------------------------//
414// //
415// GeoPixelECCable //
416// //
417//---------------------------------------------------//
418
421 : GeoVPixelFactory (ddmgr, mgr)
422{
423 //
424 // Define the log volume in the constructor, so I do it only once.
425 //
426
427 //
428 // Dimensions
429 //
430 double rmin = m_gmt_mgr->PixelECCablesRMin();
431 double rmax = m_gmt_mgr->PixelECCablesRMax();
432 double thickness = m_gmt_mgr->PixelECCablesThickness();
433 const GeoMaterial* cableMat = m_mat_mgr->getMaterial("pix::ECCables");
434 const GeoTube* cableTube = new GeoTube(rmin,rmax,thickness*0.5);
435 m_theECCable = new GeoLogVol("ECCableLog",cableTube,cableMat);
436}
437
438GeoVPhysVol* GeoPixelECCable::Build( ) {
439 GeoPhysVol* cablePhys = new GeoPhysVol(m_theECCable);
440 return cablePhys;
441}
442
443
444//---------------------------------------------------//
445// //
446// GeoPixelEndCap //
447// //
448//---------------------------------------------------//
449
450
451GeoVPhysVol* GeoPixelEndCap::Build( ) {
452
453 //
454 // create the Barrel Mother volume
455 //
456 double rmin = m_gmt_mgr->PixelEndcapRMin();
457 double rmax = m_gmt_mgr->PixelEndcapRMax();
458 double halflength = (m_gmt_mgr->PixelEndcapZMax()-m_gmt_mgr->PixelEndcapZMin())/2.;
459 const GeoMaterial* air = m_mat_mgr->getMaterial("std::Air");
460 const GeoTube* ecTube = new GeoTube(rmin,rmax,halflength);
461 const GeoLogVol* ecLog = new GeoLogVol("EndCapLog",ecTube,air);
462 GeoPhysVol* ecPhys = new GeoPhysVol(ecLog);
463
464 // Set numerology
466
467 //
468 // Place the disks and cables on both sides
469 //
472 for(int ii = 0; ii < m_gmt_mgr->PixelEndcapNDisk(); ii++) {
474 if(m_gmt_mgr->isLDPresent()) {
475 //
476 // The position is given w.r.t to the center of the detector!
477 //
478 // position of the endcap
479 double ecz = (m_gmt_mgr->PixelEndcapZMax()+m_gmt_mgr->PixelEndcapZMin())/2.;
480 //position of the disk
481 double zdisk = m_gmt_mgr->PixelDiskPosition()-ecz;
482 // place the disk
483 GeoTrf::Translate3D pos(0.,0.,zdisk);
484 GeoNameTag* tag = new GeoNameTag("Disk");
485 GeoAlignableTransform* xform = new GeoAlignableTransform(pos);
486 GeoVPhysVol * diskPhys = pd.Build();
487 ecPhys->add(tag);
488 ecPhys->add(new GeoIdentifierTag(ii));
489 ecPhys->add(xform);
490 ecPhys->add(diskPhys);
491
492 // Store the alignable transform
493 int brl_ec = 2*m_gmt_mgr->GetSide();
494 Identifier id = m_gmt_mgr->getIdHelper()->wafer_id(brl_ec,ii,0,0);
495 m_DDmgr->addAlignableTransform(1, id, xform, diskPhys);
496
497 //
498 // place the cables twice for the two active parts
499 //
500 double dz = pd.Thickness()/2. + m_gmt_mgr->PixelECCablesDistance() ;
501 pos = GeoTrf::Translate3D(0.,0.,zdisk+dz);
502 tag = new GeoNameTag("ECCables");
503 GeoTransform * xformCablesPlus = new GeoTransform(pos);
504 ecPhys->add(tag);
505 ecPhys->add(xformCablesPlus);
506 ecPhys->add(pecc.Build() );
507 pos = GeoTrf::Translate3D(0.,0.,zdisk-dz);
508 tag = new GeoNameTag("ECCables");
509 GeoTransform * xformCablesMinus = new GeoTransform(pos);
510 ecPhys->add(tag);
511 ecPhys->add(xformCablesMinus);
512 ecPhys->add(pecc.Build() );
513 } else {
514 if(m_gmt_mgr->msgLvl(MSG::DEBUG)) m_gmt_mgr->msg(MSG::DEBUG) << "Disk " << ii << " not built" << endmsg;
515
516 }
517 }
518 if(m_gmt_mgr->DoServices() ) {
519 //
520 // Add the Endcap services inide the EC volume
521 //
522 GeoPixelServices ecsvc = GeoPixelServices(m_DDmgr, m_gmt_mgr, "/Pixel/PixelEndcap");
523 for(int ii =0; ii< ecsvc.NCylinders(); ii++) {
524 ecsvc.SetCylinder(ii);
525 GeoNameTag* tag = new GeoNameTag("Outside Endcap Service");
526 GeoTrf::Translate3D pos(0.,0.,ecsvc.ZPos() );
527 GeoTransform* xform = new GeoTransform(pos);
528 ecPhys->add(tag);
529 ecPhys->add(xform);
530 ecPhys->add(ecsvc.Build() );
531 }
532 }
533 return ecPhys;
534}
535
536//---------------------------------------------------//
537// //
538// GeoPixelEnvelope //
539// //
540//---------------------------------------------------//
541
542
543GeoVPhysVol* GeoPixelEnvelope::Build( ) {
544 //
545 // create the External volume where I'll put all the pixel detector
546 //
547 double rmin = m_gmt_mgr->PixelRMin();
548 double rmax = m_gmt_mgr->PixelRMax();
549 double halflength = m_gmt_mgr->PixelHalfLength();
550 //std::cout << "Material Manager " << m_mat_mgr << std::endl;
551 const GeoMaterial* air = m_mat_mgr->getMaterial("std::Air");
552 const GeoTube* envelopeTube = new GeoTube(rmin,rmax,halflength);
553 const GeoLogVol* envelopeLog = new GeoLogVol("Pixel",envelopeTube,air);
554 GeoFullPhysVol* envelopePhys = new GeoFullPhysVol(envelopeLog);
555 //
556 // Add the Barrel:
557 //
558 m_DDmgr->numerology().addBarrel(0);
559 m_gmt_mgr->SetBarrel();
560 GeoPixelBarrel brl (m_DDmgr, m_gmt_mgr);
561 GeoNameTag* tag = new GeoNameTag("Barrel");
562 GeoVPhysVol* barrelPhys = brl.Build() ;
563 envelopePhys->add(tag);
564 envelopePhys->add(new GeoIdentifierTag(0));
565 envelopePhys->add(barrelPhys );
566 if(m_gmt_mgr->DoServices() ) {
567 //
568 // Add the Barrel services outside the barrel volume
569 //
570 GeoPixelServices brlsvc = GeoPixelServices(m_DDmgr, m_gmt_mgr, "/Pixel");
571 for(int ii =0; ii< brlsvc.NCylinders(); ii++) {
572 brlsvc.SetCylinder(ii);
573 GeoNameTag* tag = new GeoNameTag("Outside Barrel Service");
574 GeoTrf::Translate3D pos(0.,0.,brlsvc.ZPos() );
575 GeoTransform* xform = new GeoTransform(pos);
576 envelopePhys->add(tag);
577 envelopePhys->add(new GeoIdentifierTag(ii) );
578 envelopePhys->add(xform);
579 envelopePhys->add(brlsvc.Build() );
580 }
581 }
582 //
583 // Add the EndCaps
584 //
585 m_DDmgr->numerology().addEndcap(2);
586 m_DDmgr->numerology().addEndcap(-2);
587 m_gmt_mgr->SetEndcap();
588 m_gmt_mgr->SetPos();
589 GeoPixelEndCap pec (m_DDmgr, m_gmt_mgr);
590 double zpos = (m_gmt_mgr->PixelEndcapZMax()+m_gmt_mgr->PixelEndcapZMin())/2.;
591 GeoTrf::Translate3D pos(0.,0.,zpos);
592 GeoTransform* xform = new GeoTransform(pos);
593 tag = new GeoNameTag("EndCap 1");
594 envelopePhys->add(tag);
595 envelopePhys->add(new GeoIdentifierTag(2));
596 envelopePhys->add(xform);
597 envelopePhys->add(pec.Build() );
598 m_gmt_mgr->SetNeg();
599 GeoTrf::RotateX3D rm(180.*Gaudi::Units::deg);
600 xform = new GeoTransform(GeoTrf::Transform3D(GeoTrf::Translation3D(0.,0.,-zpos)*rm));
601 tag = new GeoNameTag("EndCap 2");
602 envelopePhys->add(tag);
603 envelopePhys->add(new GeoIdentifierTag(-2));
604 envelopePhys->add(xform);
605 envelopePhys->add(pec.Build() );
606 if(m_gmt_mgr->DoServices() ) {
607 //
608 // Add the Endcap services outside the EC volume
609 //
610 GeoPixelServices ecsvc = GeoPixelServices(m_DDmgr, m_gmt_mgr, "/Pixel");
611 for(int ii =0; ii< ecsvc.NCylinders(); ii++) {
612 ecsvc.SetCylinder(ii);
613 GeoNameTag* tag = new GeoNameTag("Outside Endcap Service");
614 GeoTrf::Translate3D pos(0.,0.,ecsvc.ZPos() );
615 GeoTransform* xform = new GeoTransform(pos);
616 envelopePhys->add(tag);
617 envelopePhys->add(xform);
618 envelopePhys->add(new GeoIdentifierTag(ii) );
619 envelopePhys->add(ecsvc.Build() );
620 }
621 }
622 return envelopePhys;
623
624 //
625 // Want other stuff?
626 //
627 // GeoPixelLadder brl;
628 // GeoPixelTubeCables brl;
629 // GeoPixelModule brl;
630
631
632}
633
634
635//---------------------------------------------------//
636// //
637// GeoPixelHybrid //
638// //
639//---------------------------------------------------//
640
641//
642// This class builds one Hybrid to be placed in one module
643//
644// The information on which layer to build is retrieved by the Geometry Manager
645//
646// Contained by: PixelModule_log
647//
648// Contains: nothing
649//
650
651GeoVPhysVol* GeoPixelHybrid::Build() {
652 //
653 // Dimensions
654 //
655 double length = m_gmt_mgr->PixelHybridLength();
656 double thickness = m_gmt_mgr->PixelHybridThickness();
657 double width = m_gmt_mgr->PixelHybridWidth();
658 const GeoMaterial* hybridMat = m_mat_mgr->getMaterial("pix::Hybrid");
659 if(m_gmt_mgr->isEndcap() )hybridMat = m_mat_mgr->getMaterial("std::Silicon");
660 const GeoBox* hybridBox = new GeoBox(thickness/2.,width/2.,length/2.);
661 std::string logName = "hybridECLog";
662 if(m_gmt_mgr->isBarrel() ) logName = "hybridBrlLog";
663 GeoLogVol* theHybrid = new GeoLogVol(logName,hybridBox,hybridMat);
664 GeoPhysVol* hybridPhys = new GeoPhysVol(theHybrid);
665 return hybridPhys;
666}
667
668//---------------------------------------------------//
669// //
670// GeoPixelLadder //
671// //
672//---------------------------------------------------//
673
674
677 GeoPixelSiCrystal& theSensor)
678 : GeoVPixelFactory (ddmgr, mgr),
679 m_theSensor(theSensor)
680{
681 using std::max;
682
683 //
684 // Define the log volume in the constructor, so I do it only once.
685 //
686
687 //
688 // Length of the ladder is in the db
689 //
690 double halflength = m_gmt_mgr->PixelLadderHalfLength();
691 //
692 // The width is the maximum among the componenst widths
693 //
694 double width = max( max(
695 m_gmt_mgr->PixelBoardWidth(),
696 m_gmt_mgr->PixelHybridWidth()),
697 m_gmt_mgr->PixelChipWidth());
698 //
699 // The thickness has to be calculated
700 //
701 double thickness = this->Thickness();
702 const GeoMaterial* air = m_mat_mgr->getMaterial("std::Air");
703 const GeoBox* ladderBox = new GeoBox(thickness*0.5,width*0.5,halflength);
704 m_theLadder = new GeoLogVol("ladderLog",ladderBox,air);
705}
706
707GeoVPhysVol* GeoPixelLadder::Build( ) {
708 GeoPhysVol* ladderPhys = new GeoPhysVol(m_theLadder);
709 //
710 // Place the Modules
711 //
713 int HalfNModule = m_gmt_mgr->PixelNModule()/2;
714 for(int ii = 0; ii < m_gmt_mgr->PixelNModule(); ii++) {
715 //
716 // Which of the two sides is it?
717 //
718 float side = 1.;
719 int jj = ii-HalfNModule;
720 m_gmt_mgr->SetEta(jj);
721 if(jj < 0) {
722 side = -1.;
723 jj = -jj;
724 }
725//
726// Shift down the central module, as its flag (from NOVA) is -1.
727//
729//
730// Get the z position from the db
731//
732 float zpos = m_gmt_mgr->PixelModulePosition(jj)*side;
733 GeoTrf::Translation3D modulepos(xpos,0.,zpos);
734//
735//
736//
737 //
738 // again change sign w.r.t. g4
739 //
740 GeoTrf::RotateY3D rm(m_gmt_mgr->PixelModuleAngle()*m_gmt_mgr->PixelModuleAngleSign(ii) );
741//
742// Place the Module
743//
744 GeoVPhysVol* modulephys = pm.Build() ;
745 GeoNameTag *tag = new GeoNameTag("Module");
746 GeoAlignableTransform* xform;
747 // OLD EXAMPLE FOR ALIGNEMENT!!
748 // if(m_gmt_mgr->IsAlign() ) {
749 // xform = new GeoSiAlTransform(GeoTrf::Transform3D(rm,modulepos), pm.getID() );
750 // } else {
751 // xform = new GeoTransform(GeoTrf::Transform3D(rm,modulepos));
752 // }
753 xform = new GeoAlignableTransform(GeoTrf::Transform3D(modulepos*rm));
754 ladderPhys->add(tag);
755 ladderPhys->add(new GeoIdentifierTag(m_gmt_mgr->Eta() ) );
756 ladderPhys->add(xform);
757 ladderPhys->add(modulephys );
758
759 // Now store the xform by identifier:
761 m_DDmgr->addAlignableTransform(0,id,xform,modulephys);
762
763 }
764 return ladderPhys;
765}
766
767
769 //
770 // The thickness of the ladderis calculated starting from the thickness of
771 // its components: Board + Hybrid+Chips
772 // then the distance of the modules from the center is added and
773 // a factor is added to account for the tilt of ~1degree given to
774 // have a z overlap of the single modules
775 //
776 double tckincl = (m_gmt_mgr->PixelBoardLength()+m_gmt_mgr->PixelBalcony())*
777 sin(m_gmt_mgr->PixelModuleAngle())/2.;
778 double thick = m_gmt_mgr->PixelBoardThickness()+
779 m_gmt_mgr->PixelHybridThickness()+
780 m_gmt_mgr->PixelChipThickness()+
781 fabs(m_gmt_mgr->PixelModuleDrDistance())+
782 tckincl;
783 return thick;
784}
785
786
787//---------------------------------------------------//
788// //
789// GeoPixelLadderStruct //
790// //
791//---------------------------------------------------//
792
793
795 //
796 // create the structure to hold the ladder
797 //
798 //
799 // Dimensions
800 //
801 double halflength = m_gmt_mgr->PixelLadderHalfLength();
802 double thickness = m_gmt_mgr->PixelLadderThickness();
803 double width = m_gmt_mgr->PixelLadderWidth();
804 //
805 // This is ladder material
806 //
807 const GeoMaterial* ladderMat = m_mat_mgr->getMaterial("pix::Ladder");
808 const GeoBox* ladderStructBox = new GeoBox(thickness/2.,width/2.,halflength);
809 const GeoLogVol* ladderStructLog = new GeoLogVol("ladderStructLog",ladderStructBox,ladderMat);
810 GeoPhysVol* ladderStructPhys = new GeoPhysVol(ladderStructLog);
811 return ladderStructPhys;
812}
813
814
815//---------------------------------------------------//
816// //
817// GeoPixelLayer //
818// //
819//---------------------------------------------------//
820
821
822GeoVPhysVol* GeoPixelLayer::Build() {
823
824 //
825 // create the three barrel layers
826 // Build the sensor first to use the same for all the module in the layer
827 bool isBLayer = false;
828 if(m_gmt_mgr->GetLD() == 0) isBLayer = true;
829 GeoPixelSiCrystal theSensor(m_DDmgr, m_gmt_mgr, isBLayer);
830 //
831 // This is the maximum possible w/o going out of the mother volume!
832 //
833 double LayerThickness = 8.499*Gaudi::Units::mm;
834 const GeoMaterial* air = m_mat_mgr->getMaterial("std::Air");
835 //
836 // Layer dimensions from the geometry manager
837 //
838 double rmin = m_gmt_mgr->PixelLayerRadius()-LayerThickness;
839 double rmax = m_gmt_mgr->PixelLayerRadius()+LayerThickness;
840 double halflength = m_gmt_mgr->PixelLadderHalfLength() + m_epsilon;
841 std::string lname[3];
842 lname[0] = "InnerLayerLog";
843 lname[1] = "CenterLayerLog";
844 lname[2] = "OuterLayerLog";
845 const GeoTube* layerTube = new GeoTube(rmin,rmax,halflength); //solid
846 const GeoLogVol* layerLog = new GeoLogVol(lname[m_gmt_mgr->GetLD()],layerTube,air); //log volume
847 GeoFullPhysVol* layerPhys = new GeoFullPhysVol(layerLog); // phys vol
848 //
849 // Place the ladders:
850 //
851 GeoPixelLadder pl(m_DDmgr, m_gmt_mgr, theSensor);
853 int nsectors = m_gmt_mgr->NPixelSectors();
854 double angle=360./nsectors*Gaudi::Units::deg;
855 double layerradius = m_gmt_mgr->PixelLayerRadius();
856 double xcblpos = layerradius + (pl.Thickness()/2.+ptc.Thickness()/2)/cos(m_gmt_mgr->PixelLadderTilt());
857 GeoTrf::Vector3D posladder(layerradius, 0.,0.);
858 posladder = GeoTrf::RotateZ3D(angle/2.)*posladder;
859 GeoTrf::Vector3D postubecables(xcblpos, 0.,0.);
860 postubecables = GeoTrf::RotateZ3D(angle/2.)*postubecables;
861
862 // Set numerology
865
866 //
867 // Place the volumes by rotation.
868 //
869 for(int ii = 0; ii < nsectors; ii++) {
870 m_gmt_mgr->SetPhi(ii);
871 //
872 // change the sign w.r.t G4 (same sign as G3)
873 //
874 GeoTrf::RotateZ3D rm(( +(float) ii+0.5)*angle+m_gmt_mgr->PixelLadderTilt() );
875 //
876 // Place the ladders
877 //
878 GeoNameTag *tag = new GeoNameTag("Ladder");
879 GeoTransform* xform = new GeoTransform(GeoTrf::Translate3D(posladder.x(),posladder.y(),posladder.z())*rm);
880 layerPhys->add(tag);
881 layerPhys->add(new GeoIdentifierTag(ii) );
882 layerPhys->add(xform);
883 GeoVPhysVol* ladderphys = pl.Build() ;
884 layerPhys->add(ladderphys );
885 posladder = GeoTrf::RotateZ3D(angle)*posladder;
886 if(m_gmt_mgr->DoServices() ) {
887 //
888 // Place the box w/ the tubes and cables for the layer
889 //
890 tag = new GeoNameTag("TubesAndCables");
891 xform = new GeoTransform(GeoTrf::Translate3D(postubecables.x(),postubecables.y(),postubecables.z())*rm);
892 layerPhys->add(tag);
893 layerPhys->add(xform);
894 GeoVPhysVol* TCphys = ptc.Build() ;
895 layerPhys->add(TCphys );
896 postubecables = GeoTrf::RotateZ3D(angle)*postubecables;
897 }
898 }
899 return layerPhys;
900}
901
902
903//---------------------------------------------------//
904// //
905// GeoPixelModule //
906// //
907//---------------------------------------------------//
908
909
912 GeoPixelSiCrystal& theSensor) :
913 GeoVPixelFactory (ddmgr, mgr),
914 m_theSensor(theSensor)
915{
916 //
917 // Define the log volume in the constructor, so I do it only once.
918 //
919 //
920 // The Dimensions are in separate routines
921 //
922 double length = this->Length();
923 double thickness = this->Thickness();
924 double width = this->Width();
925 const GeoMaterial* air = m_mat_mgr->getMaterial("std::Air");
926 const GeoBox* moduleBox = new GeoBox(thickness*0.5,width*0.5,length*0.5);
927 m_theModule = new GeoLogVol("moduleLog",moduleBox,air);
928
929}
930
931GeoVPhysVol* GeoPixelModule::Build( ) {
932 GeoFullPhysVol* modulePhys = new GeoFullPhysVol(m_theModule);
933 //
934 // Place the Si Crystal
935 //
936 GeoVPhysVol *theSi = m_theSensor.Build();
938 GeoNameTag *tag = new GeoNameTag("Si Crystal");
939 GeoTransform *xformsi = new GeoTransform(GeoTrf::Transform3D::Identity());
940 modulePhys->add(tag);
941 modulePhys->add(new GeoIdentifierTag(100) );
942 modulePhys->add(xformsi);
943 modulePhys->add(theSi );
944 //
945 // Place the Hybrid
946 //
949 GeoTrf::Translate3D hybpos(xpos,0.,0.);
950 GeoTransform* xform = new GeoTransform(hybpos);
951 tag = new GeoNameTag("Hybrid");
952 modulePhys->add(tag);
953 modulePhys->add(xform);
954 modulePhys->add(ph.Build() );
955 //
956 // Place the Chip
957 //
960 GeoTrf::Translate3D chippos(xpos,0.,0.);
961 xform = new GeoTransform(chippos);
962 tag = new GeoNameTag("Chip");
963 modulePhys->add(tag);
964 modulePhys->add(xform);
965 modulePhys->add(pc.Build() );
966 //
967 // Add the silicon element to the list of detector elements...
968 //
969 return modulePhys;
970}
971
972
974 using std::max;
975 //
976 // The thickness of the module is given by the board thickness
977 // plus the maximum b/w the hybrid and the chip+gap
978 //
979 double thick = m_gmt_mgr->PixelBoardThickness()+
982 //
983 // Don't understand why....
984 //
985 return thick+.01;
986}
987
988double GeoPixelModule::Width() {
989 using std::max;
990 double width = max( max(
991 m_gmt_mgr->PixelBoardWidth(),
992 m_gmt_mgr->PixelHybridWidth()),
993 m_gmt_mgr->PixelChipWidth());
994 return width;
995}
996double GeoPixelModule::Length() {
997 using std::max;
998 double length = max( max( max(
999 m_gmt_mgr->PixelHybridLength(),
1000 m_gmt_mgr->PixelBoardLength()),
1001 2*m_gmt_mgr->PixelBalcony()),
1002 m_gmt_mgr->PixelChipLength());
1003
1004 return length;
1005}
1006
1007Identifier GeoPixelModule::getID() {
1008 return m_id;
1009}
1010
1011//---------------------------------------------------//
1012// //
1013// GeoPixelServices //
1014// //
1015//---------------------------------------------------//
1016
1017//
1018// This class builds the Services as Cylinders
1019//
1020// The services are grouped in 4 groups (as in G3)
1021// I keep this grouping as it natural in the database.
1022// They are Barrel-Inside tracking volume
1023// Barrel-Outside tracking volume
1024// Endcap-Inside tracking volume
1025// Edncap-Outside tracking volume
1026//
1027// The elements for each group are defined in initialize,
1028// with Barrel/endcap coming from the geometry manager and inside oputside,
1029// from the mother volume name.
1030// This class builds the n-th service element, with n defined in SetCylinder
1031//
1032//
1033//
1034// The information on which layer to build is retrieved by the Geometry Manager
1035//
1036// Contained by: passed by argument
1037//
1038// Contains: nothing
1039//
1040
1041
1042GeoPixelServices::GeoPixelServices(InDetDD::PixelDetectorManager* ddmgr,
1044 const std::string& root)
1045 : GeoVPixelFactory (ddmgr, mgr)
1046{
1047 //
1048 // Initialize the service geometry properly accordning to the
1049 // mother volume where it goes.
1050 // Of course services cannot be placed in other volumes.
1051 if(root == "/Pixel") {
1052 initialize("Outside");
1053 m_zone = "Out";
1054 } else if (root == "/Pixel/PixelBarrel" || root == "/Pixel/PixelEndcap" ) {
1055 initialize("Inside");
1056 m_zone = "In";
1057 } else {
1058 std::cerr << "Services can not be placed in this volume!!!! " << root << std::endl;
1059 }
1060 m_nframe = 0;
1061}
1062
1063void GeoPixelServices::initialize(const std::string& a)
1064{
1065 //
1066 // Here I inizialize the geometry information contained in the vectors
1067 //
1068
1069 //
1070 // Loop over the service elements:
1071 //
1072 int NServices = m_gmt_mgr->PixelServiceNFrame(a);
1073 for(int ii = 0; ii<NServices ; ii++) {
1074 //
1075 // If the element is attached to a layer/disk check if the LD is present.
1076 //
1077 int LD = m_gmt_mgr->PixelServiceLD(a, ii);
1078 //
1079 // C counts from zero. So the LDs are 0,1,2. -1 correspond to a
1080 // service which is not attached to any LD.
1081 //
1082 if(LD != -1) m_gmt_mgr->SetCurrentLD(LD);
1083 if(LD ==-1 || m_gmt_mgr->isLDPresent()) {
1084 double zpos,halflength;
1085//
1086// Retrieve/calculate the parameters for the volume.
1087//
1088// Here the atlsim logic has to be interpreted, as this is going into
1089// the structure of the PBOI bank that I'm using
1090//
1091 std::string mat = m_gmt_mgr->PixelServiceMaterial(a, ii);
1092 double* r = m_gmt_mgr->PixelServiceR(a, ii);
1093 double* z = m_gmt_mgr->PixelServiceZ(a, ii);
1094 //
1095 // If zin is 0... (within 10^-5) this is a volume symmetric around
1096 // the origin
1097 //
1098 if(fabs(z[0]) < 0.000001) {
1099 zpos = 0.;
1100 halflength = fabs(z[1])-m_epsilon;
1101 } else {
1102 halflength = fabs(z[1]-z[0])/2.-m_epsilon;
1103 zpos = (z[1]+z[0])/2.+m_epsilon/2.;
1104 }
1105 //
1106 // Push the object into the vectors: (twice if needed)
1107 //
1108 //
1109 //
1110 bool twovolumes;
1111 twovolumes = zpos > 0.00001 && r[0] >0.;
1112 // only once for the inside endcaps as I already have two endcaps!
1113 if(m_gmt_mgr->isEndcap() && a == "Inside") twovolumes = false;
1114 m_rmin.push_back(fabs(r[0]));
1115 m_rmax.push_back(r[1]);
1116 m_zpos.push_back(zpos);
1117 m_halflength.push_back(halflength);
1118 m_material.push_back(mat);
1119 if(twovolumes) {
1120 m_rmin.push_back(fabs(r[0]));
1121 m_rmax.push_back(r[1]);
1122 m_zpos.push_back(-zpos);
1123 m_halflength.push_back(halflength);
1124 m_material.push_back(std::move(mat));
1125 }
1126 delete[] r;
1127 delete[] z;
1128 }
1129 //
1130 // Delete r and z...
1131 //
1132 }
1133}
1134
1135GeoVPhysVol* GeoPixelServices::Build( ) {
1136 const GeoMaterial* serviceMat = m_mat_mgr->getMaterial(m_material[m_nframe]);
1137 //
1138 // Dimensions: (m_nframe set with teh SetCylinder method)
1139 //
1140 double rmin = m_rmin[m_nframe];
1141 double rmax = m_rmax[m_nframe];
1142 double halflength = m_halflength[m_nframe];
1143 const GeoTube* serviceTube = new GeoTube(rmin,rmax,halflength);
1144 std::string logName;
1145 if(m_gmt_mgr->isBarrel() ) logName = m_zone+"Brl";
1146 else logName = m_zone+"EC";
1147 logName = logName+std::to_string(m_nframe);
1148 GeoLogVol* theService = new GeoLogVol(logName,serviceTube,serviceMat);
1149 GeoPhysVol* servicePhys = new GeoPhysVol(theService);
1150 return servicePhys;
1151}
1152
1153//---------------------------------------------------//
1154// //
1155// GeoPixelSiCrystal //
1156// //
1157//---------------------------------------------------//
1158
1159//
1160// This class builds one Si Crystal to be placed in one module
1161//
1162// The information on which layer to build is retrieved by the Geometry Manager
1163//
1164// Contained by: PixelModule_log
1165//
1166// Contains: nothing
1167//
1168
1169using namespace InDetDD;
1170
1173 bool isBLayer)
1174 : GeoVPixelFactory (ddmgr, mgr)
1175{
1176 //
1177 //Builds the design for this crystal
1178 m_isBLayer = isBLayer;
1179 //SiDetectorDesign::Axis etaAxis = SiDetectorDesign::zAxis;
1180 //SiDetectorDesign::Axis phiAxis = SiDetectorDesign::yAxis;
1181 //SiDetectorDesign::Axis depthAxis = SiDetectorDesign::xAxis;
1182 double thickness = m_gmt_mgr->PixelBoardThickness();
1183 int circuitsPerEta = m_gmt_mgr->DesignCircuitsPerColumn();
1184 int circuitsPerPhi = m_gmt_mgr->DesignCircuitsPerRow();
1185 int CellRowPerCirc = m_gmt_mgr->DesignCellRowsPerCircuit(isBLayer);
1186 int CellColPerCirc = m_gmt_mgr->DesignCellColumnsPerCircuit(isBLayer);
1187 int rowsPerCircuit = m_gmt_mgr->DesignDiodeRowsPerCircuit(isBLayer);
1188 int columnsPerCircuit = m_gmt_mgr->DesignDiodeColumnsPerCircuit(isBLayer);
1189
1190 // Add the matrix in the same way as from AGDD...
1191 //
1192 //double startRP = -m_gmt_mgr->DesignRPActiveArea()/2.;
1193 //double startZ = -m_gmt_mgr->DesignZActiveArea()/2.;
1194 //double ColSize = m_gmt_mgr->DesignZActiveArea()/m_gmt_mgr->DesignCircuitsPerRow();
1195 double pitchEtaBig = m_gmt_mgr->DesignPitchZ(isBLayer) + m_gmt_mgr->DesignGapZ()/2;
1196 double pitchPhi = m_gmt_mgr->DesignPitchRP(isBLayer);
1197 double pitchEta = m_gmt_mgr->DesignPitchZ(isBLayer);
1198
1199 InDetDD::detail::FENumbering fe_numbering = InDetDD::detail::FENumbering::kRegular; // also mirrored FE numbering for even-phi endcap modules ?
1200
1201 // assumed layout
1202 // circuit :
1204 // | .
1205 // | .
1206 // | .
1207 // +---> local-y / eta/ column
1208 //
1209 // full matrix : matrix of n-circuits n | ... | N/2
1210 // with 2 rows ----------------
1211 // 0 | ... | N/2-1
1212
1213 constexpr auto readoutTechnology = InDetDD::PixelReadoutTechnology::FEI3;
1214 constexpr auto kNDirections = InDetDD::detail::kNDirections;
1215 constexpr auto kNPixelLocations = InDetDD::detail::kNPixelLocations;
1217 readoutTechnology,
1218 std::array<int,kNDirections>{circuitsPerPhi,circuitsPerEta}, // [0]=phi/row, [1]=eta/column
1219 std::array<int,kNDirections>{rowsPerCircuit,columnsPerCircuit}, // [0]=phi/row, [1]=eta/column
1220 std::array<std::array<double,kNDirections>,kNPixelLocations>{ // regular/central,longEnd/outer,long/inner
1221 std::array<double,kNDirections>{pitchPhi,pitchEta},
1222 std::array<double,kNDirections>{0.,pitchEtaBig},
1223 std::array<double,kNDirections>{0.,pitchEtaBig}},
1224 fe_numbering);
1225
1226 std::unique_ptr<PixelModuleDesign> p_barrelDesign2 = std::make_unique<PixelModuleDesign>(thickness,
1227 circuitsPerEta,
1228 circuitsPerPhi,
1229 CellColPerCirc,
1230 CellRowPerCirc,
1231 columnsPerCircuit,
1232 rowsPerCircuit,
1233 std::move(diode_tree),
1235 -1, /* readout side */
1236 false, /* 3D */
1237 InDetDD::Undefined, /* detector type */
1238 readoutTechnology);
1239
1240 // Multiple connections (ganged pixels)
1241 if (m_gmt_mgr->NumberOfEmptyRows() > 0) {
1242 int minRow = m_gmt_mgr->EmptyRows(0);
1243 int maxRow = minRow;
1244
1245
1246 for (int iConnect = 0; iConnect < m_gmt_mgr->NumberOfEmptyRows(); iConnect++){
1247 minRow = std::min(minRow, m_gmt_mgr->EmptyRows(iConnect));
1248 minRow = std::min(minRow, m_gmt_mgr->EmptyRowConnections(iConnect));
1249 maxRow = std::max(maxRow, m_gmt_mgr->EmptyRows(iConnect));
1250 maxRow = std::max(minRow, m_gmt_mgr->EmptyRowConnections(iConnect));
1251 }
1252
1253 std::vector <int> connections(maxRow-minRow+1);
1254
1255 // We fill them all with a one to one correspondence first.
1256 for (unsigned int iRow = 0; iRow < connections.size(); iRow++){
1257 connections[iRow] = iRow + minRow;
1258 }
1259
1260 // Now make the connections.
1261 for (int iConnect = 0; iConnect < m_gmt_mgr->NumberOfEmptyRows(); iConnect++){
1262 connections[m_gmt_mgr->EmptyRows(iConnect)-minRow] = m_gmt_mgr->EmptyRowConnections(iConnect);
1263 }
1264
1265 //std::cout << "MinRow = " << minRow << std::endl;
1266 //std::cout << "MaxRow = " << maxRow << std::endl;
1267 //for (unsigned int iRow = 0; iRow < connections.size(); iRow++){
1268 // std::cout << iRow << " " << connections[iRow] << std::endl;
1269 //}
1270
1271 p_barrelDesign2->addMultipleRowConnection(minRow, connections);
1272
1273 } else {
1274 // No empty rows.
1275 std::cout << "GeoPixelSiCrystal: Warning - No ganged pixels" << std::endl;
1276 }
1277
1278
1279 m_design = m_DDmgr->addDesign(std::move(p_barrelDesign2));
1280
1281}
1282GeoVPhysVol* GeoPixelSiCrystal::Build() {
1283 //
1284 // Dimensions
1285 //
1286 double length = m_gmt_mgr->PixelBoardLength();
1287 double thickness = m_gmt_mgr->PixelBoardThickness();
1288 double width = m_gmt_mgr->PixelBoardWidth();
1289 const GeoMaterial* siMat = m_mat_mgr->getMaterial("std::Silicon");
1290 const GeoBox* siBox = new GeoBox(thickness/2.,width/2.,length/2.);
1291 std::string logname;
1292 if(m_isBLayer) logname = "siBLayLog";
1293 else logname = "siLog";
1294 GeoLogVol* theSi = new GeoLogVol(logname,siBox,siMat);
1295 GeoFullPhysVol* siPhys = new GeoFullPhysVol(theSi);
1296 //
1297 // Add this to the list of detector elements:
1298 //
1299 int brl_ec=0;
1300 //
1301 // Build the Identifier for the silicon:
1302 //
1303 if(m_gmt_mgr->isBarrel() ) brl_ec = 0;
1304 if(m_gmt_mgr->isEndcap() ) brl_ec = 2*m_gmt_mgr->GetSide();
1305 const PixelID *ppp = m_gmt_mgr->getIdHelper();
1306 Identifier idwafer;
1307 if(brl_ec == 0) {
1308 idwafer = ppp->wafer_id(brl_ec,m_gmt_mgr->GetLD(),m_gmt_mgr->Phi(),m_gmt_mgr->Eta());
1309 } else {
1310 int phimod;
1311 //
1312 // This is evaluating the phimod. It's a bit complicated as I have to
1313 // assign the numbers corresponding to a counter-clockwise rotation
1314 // in the disk reference frame. For the (eta) positive endcap I just
1315 // have to match the start position with the start of the rotation.
1316 //
1317 if(brl_ec == 2) {
1318 phimod = m_gmt_mgr->Phi()*2 + m_gmt_mgr->Eta();
1319 } else {
1320 //
1321 // The (eta) negative) endcap is more complicated, as there is an extra
1322 // rotation of the endcap as a whole around Y
1323 //
1324 phimod = 48-m_gmt_mgr->Phi()*2-m_gmt_mgr->Eta()-2;
1325 if (phimod == -1) phimod = 47;
1326 }
1327
1328 idwafer = ppp->wafer_id(brl_ec,m_gmt_mgr->GetLD(),phimod,0);
1329 }
1330 m_id=idwafer;
1331
1332 SiDetectorElement * element = new SiDetectorElement(idwafer, m_design, siPhys, m_gmt_mgr->commonItems());
1333 // Add conditions: (do it here as eventually they will come from the cond DB)
1334 //SiliconConditions conditions(m_gmt_mgr->Temperature(m_isBLayer), m_gmt_mgr->Voltage(m_isBLayer), 0.);
1335 //element->setSiliconConditions(conditions);
1336 // Pass on G3ComptibleDigits option.
1337 // NO LONGER POSSIBLE. DC1 not supported anyway.
1338 // element->setG3CompatibleOrientation(m_gmt_mgr->G3CompatibleDigits());
1339 // add the element to the manager
1340 m_DDmgr->addDetectorElement(element);
1341 return siPhys;
1342}
1343
1344//---------------------------------------------------//
1345// //
1346// GeoPixelSubDisk //
1347// //
1348//---------------------------------------------------//
1349
1350
1353 GeoPixelSiCrystal & theSensor)
1354 : GeoVPixelFactory (ddmgr, mgr),
1355 m_theSensor(theSensor)
1356{
1357 //
1358 // Define the log volume in the constructor, so I do it only once.
1359 //
1360
1361 //
1362 // Dimensions from class methods.
1363 //
1364 double rmin = RMin();
1365 double rmax = RMax();
1366 double halflength = Thickness()/2.;
1367 const GeoMaterial* air = m_mat_mgr->getMaterial("std::Air");
1368 const GeoTubs* SDTubs = new GeoTubs(rmin,rmax,halflength,-180.*Gaudi::Units::deg/m_gmt_mgr->PixelECNSectors1()+0.000005,360.*Gaudi::Units::deg/m_gmt_mgr->PixelECNSectors1()-0.00001);
1369 m_theSubDisk = new GeoLogVol("SubDiskLog",SDTubs,air);
1370
1371}
1372
1373
1374GeoVPhysVol* GeoPixelSubDisk::Build( ) {
1375 GeoFullPhysVol* SDPhys = new GeoFullPhysVol(m_theSubDisk);
1376 //
1377 // Place the Si Crystal
1378 //
1379 double xpos = RMin()+m_gmt_mgr->PixelBoardLength()/2.;
1380 GeoNameTag* tag = new GeoNameTag("SiCrystal");
1381 GeoTrf::Transform3D rm = GeoTrf::RotateX3D(180.*Gaudi::Units::deg)*GeoTrf::RotateY3D(90.*Gaudi::Units::deg);
1382 GeoTrf::Translation3D pos(xpos,0.,0.);
1383 GeoAlignableTransform* xformsi = new GeoAlignableTransform(GeoTrf::Transform3D(pos*rm));
1384 SDPhys->add(tag);
1385 SDPhys->add(new GeoIdentifierTag(200) );
1386 SDPhys->add(xformsi);
1387 SDPhys->add(m_theSensor.Build() );
1388 //
1389 // Place the Hybrid
1390 //
1392 tag = new GeoNameTag("Hybrid");
1393 double zpos = 0.5*(m_gmt_mgr->PixelBoardThickness()+m_gmt_mgr->PixelHybridThickness())+m_epsilon/2.;
1394 pos = GeoTrf::Translation3D(xpos,0.,zpos);
1395 GeoTransform* xform = new GeoTransform(GeoTrf::Transform3D(pos*rm) );
1396 SDPhys->add(tag);
1397 SDPhys->add(xform);
1398 SDPhys->add(ph.Build() );
1399//
1400// Place the Chip
1401//
1403 tag = new GeoNameTag("Chip");
1404 zpos = -0.5*(m_gmt_mgr->PixelBoardThickness()+m_gmt_mgr->PixelChipThickness())-m_gmt_mgr->PixelChipGap();
1405 pos = GeoTrf::Translation3D(xpos,0.,zpos);
1406 xform = new GeoTransform(GeoTrf::Transform3D(pos*rm) );
1407 SDPhys->add(tag);
1408 SDPhys->add(xform);
1409 SDPhys->add(pc.Build() );
1410 return SDPhys;
1411}
1412
1413
1415 return m_gmt_mgr->PixelDiskRMin()-0.5*(m_gmt_mgr->PixelBoardLength()-m_gmt_mgr->PixelBoardActiveLen());
1416}
1417
1419 return RMin()+sqrt(pow(m_gmt_mgr->PixelBoardLength(),2)+pow(m_gmt_mgr->PixelBoardWidth(),2));
1420}
1421
1423 //
1424 // This is the sum of the Thickness of the board + twice the maximum
1425 // b/w the thickness of the hybrid and that of the electronics
1426 // twice for symmetric placement.
1427 //
1428
1429 return m_gmt_mgr->PixelBoardThickness()+2*std::max(m_gmt_mgr->PixelHybridThickness(),m_gmt_mgr->PixelChipThickness())+2*m_epsilon;
1430}
1431
1432//---------------------------------------------------//
1433// //
1434// GeoPixelTubeCables //
1435// //
1436//---------------------------------------------------//
1437
1438
1441 : GeoVPixelFactory (ddmgr, mgr)
1442{
1443 //
1444 // Define the log volume in the constructor, so I do it only once.
1445 //
1446
1447 //
1448 // Length is in the db
1449 //
1450 double halflength = m_gmt_mgr->PixelLadderHalfLength();
1451 //
1452 // The width is the maximum among the componenst widths
1453 //
1454 double width = std::max(m_gmt_mgr->PixelLadderWidth(),
1455 m_gmt_mgr->PixelCableWidth());
1456 //
1457 // The thickness has to be calculated
1458 //
1459 double thickness = this->Thickness();
1460 const GeoMaterial* air = m_mat_mgr->getMaterial("std::Air");
1461 const GeoBox* solBox = new GeoBox(thickness*0.5,width*0.5,halflength+m_epsilon);
1462 m_theBox = new GeoLogVol("TubeCablesLog",solBox,air);
1463
1464}
1465
1466
1468 GeoPhysVol* TCPhys = new GeoPhysVol(m_theBox);
1469 //
1470 // Place the Ladder Structure. Don't understand why this is going in the
1471 // tube & cables section...
1472 //
1474 GeoNameTag* tag = new GeoNameTag("LadderStructure");
1475 GeoVPhysVol* ladderstructPhys = pls.Build() ;
1476 double xpos = 0.5*(-this->Thickness()+m_gmt_mgr->PixelLadderThickness());
1477 GeoTrf::Translate3D pos(xpos,0.,0.);
1478 GeoTransform* xform = new GeoTransform(pos);
1479 TCPhys->add(tag);
1480 TCPhys->add(xform);
1481 TCPhys->add(ladderstructPhys);
1482 //
1483 // Place the cables... ouch!
1484 //
1485 // I do it in a symmetric way, assuming that the routing of the
1486 // central module is done half on the right and half on the left.
1487 // thus I have 7 cables running on each side.
1488 //
1490 double xcabshift = 0.;
1491 for(int ii = 0; ii <= m_gmt_mgr->PixelNModule()/2; ii++) {
1492 pc.SetModuleNumber(ii);
1493 double zcabpos = m_gmt_mgr->PixelCableZMax()-pc.Length()/2.+m_epsilon/2.;
1494 xcabshift += pc.Thickness()/2.;
1495 double xcabpos = - this->Thickness()/2. + m_gmt_mgr->PixelLadderThickness()+xcabshift;
1496 //
1497 // Place the cables on both sides.
1498 // piling them up. this is slightly different from what in G3
1499 // where the cables are not piled up, I don't see a good reason for
1500 // that. In G3 there is an empty space b/w the cable from the center
1501 // and the cable from the first module, as the shift is not calculated
1502 // in the same way.
1503 //
1504 xcabshift += pc.Thickness()/2.;
1505 GeoTrf::Translate3D cablepos(xcabpos,0.,zcabpos);
1506 GeoTransform* xform = new GeoTransform(cablepos);
1507 GeoNameTag *tag = new GeoNameTag("Cable");
1508 //
1509 // Left side
1510 //
1511 GeoVPhysVol *cablePhys1 = pc.Build();
1512 TCPhys->add(tag);
1513 TCPhys->add(xform);
1514 // TCPhys->add(new GeoIdentifierTag(ii) );
1515 TCPhys->add(cablePhys1);
1516 //
1517 // Right side
1518 //
1519 GeoVPhysVol *cablePhys2 = pc.Build();
1520 cablepos = GeoTrf::Translate3D(xcabpos,0.,-zcabpos);
1521 xform = new GeoTransform(cablepos);
1522 TCPhys->add(tag);
1523 TCPhys->add(xform);
1524 // TCPhys->add(new GeoIdentifierTag(ii+100) );
1525 TCPhys->add(cablePhys2);
1526 }
1527
1528 return TCPhys;
1529}
1530
1531
1533 //
1534 // The thickness of the box is calculated starting from the thickness of
1535 // its components: Ladder + cables
1536 //
1537 double thick = m_gmt_mgr->PixelLadderThickness()+
1538 m_gmt_mgr->PixelCableThickness();
1539 return thick;
1540}
1541
1542
1543
1544
1545//---------------------------------------------------//
1546// //
1547// GeoVPixelFactor //
1548// //
1549//---------------------------------------------------//
1550
1552
1554 PixelGeometryManager* mgr) :
1555 m_gmt_mgr (mgr),
1556 m_mat_mgr (m_gmt_mgr->getMaterialManager()),
1557 m_DDmgr (ddmgr),
1558 m_epsilon(0.0001)
1559{
1560}
1561
1563{}
1564
1565
1566//---------------------------------------------------//
1567// //
1568// OraclePixGeoManager //
1569// //
1570//---------------------------------------------------//
1571
1572
1574
1575
1576using namespace std;
1577
1579 : m_eta(0),
1580 m_phi(0),
1581 m_currentLD(0),
1582 m_BarrelEndcap(0),
1583 m_side(0),
1584 m_services(true),
1585 m_g3CompatibleDigits(false),
1586 m_initialLayout(false),
1587 m_dc1Geometry(false),
1588 m_alignable(true),
1589 m_commonItems(nullptr),
1590 m_pDDmgr(nullptr),
1591 m_pMatMgr(nullptr)
1592{
1593
1594
1595 // Get service locator from Bootstrap
1596 ISvcLocator* svcLocator = Gaudi::svcLocator(); // from Bootstrap
1597
1598 ATH_MSG_DEBUG("Using ORACLE PIXEL GEOMETRY MANAGER");
1599
1600 // Get the DetStore
1601 SmartIF<StoreGateSvc> detStore{svcLocator->service("DetectorStore")};
1602 if (!detStore.isValid()) ATH_MSG_FATAL("Could not locate DetectorStore");
1603 m_pDetStore = detStore.get();
1604
1605 SmartIF<IRDBAccessSvc> rdbSvc{svcLocator->service("RDBAccessSvc")};
1606 if (!rdbSvc.isValid()) ATH_MSG_FATAL("Could not locate RDBAccessSvc");
1607
1608
1609 // Get version tag and node for Pixel.
1610 DecodeVersionKey versionKey("Pixel");
1611 const std::string& detectorKey = versionKey.tag();
1612 const std::string& detectorNode = versionKey.node();
1613
1614 m_versionTag = rdbSvc->getChildTag("Pixel", versionKey.tag(), versionKey.node());
1615
1616
1618//
1619// Gets the structures from the det store
1620//
1622
1623 ATH_MSG_INFO("Retrieving Record Sets from database ...");
1624
1625 DecodeVersionKey versionKeyAtlas("Pixel");
1626 m_atls = rdbSvc->getRecordsetPtr("AtlasMother",versionKeyAtlas.tag(), versionKeyAtlas.node());
1627 m_PixelBarrelGeneral = rdbSvc->getRecordsetPtr("PixelBarrelGeneral", detectorKey, detectorNode);
1628 m_PixelBarrelService = rdbSvc->getRecordsetPtr("PixelBarrelService", detectorKey, detectorNode);
1629 m_PixelCommon = rdbSvc->getRecordsetPtr("PixelCommon", detectorKey, detectorNode);
1630 m_PixelDisk = rdbSvc->getRecordsetPtr("PixelDisk", detectorKey, detectorNode);
1631 m_PixelEndcapGeneral = rdbSvc->getRecordsetPtr("PixelEndcapGeneral", detectorKey, detectorNode);
1632 m_PixelEndcapService = rdbSvc->getRecordsetPtr("PixelEndcapService", detectorKey, detectorNode);
1633 m_PixelLayer = rdbSvc->getRecordsetPtr("PixelLayer", detectorKey, detectorNode);
1634 m_PixelModule = rdbSvc->getRecordsetPtr("PixelModule", detectorKey, detectorNode);
1635 m_PixelStave = rdbSvc->getRecordsetPtr("PixelStave", detectorKey, detectorNode);
1636
1637
1638 // These are for the design
1639 m_pxbi = rdbSvc->getRecordsetPtr("PXBI", detectorKey, detectorNode);
1640 m_pxei = rdbSvc->getRecordsetPtr("PXEI", detectorKey, detectorNode);
1641 m_pdch = rdbSvc->getRecordsetPtr("PDCH", detectorKey, detectorNode);
1642 m_pxbd = rdbSvc->getRecordsetPtr("PXBD", detectorKey, detectorNode);
1643 m_plor = rdbSvc->getRecordsetPtr("PLOR", detectorKey, detectorNode);
1644 m_plrn = rdbSvc->getRecordsetPtr("PLRN", detectorKey, detectorNode);
1645
1646 ATH_MSG_INFO("... Record Sets retrieved.");
1647
1648 // cache the number of inner frames
1649
1650 m_barrelInFrames = (*m_PixelBarrelGeneral)[0]->getInt("NFRAMEIN");
1651 m_endcapInFrames = (*m_PixelEndcapGeneral)[0]->getInt("NFRAMEIN");
1652 //
1653 // Get the mat manager from the store:
1654 //
1655 StoredMaterialManager* materialManager = nullptr;
1656 if (StatusCode::SUCCESS == m_pDetStore->retrieve(materialManager, std::string("MATERIALS"))) {
1657 m_pMatMgr = materialManager;
1658 }
1659 //
1660 // Print the version number for the barrel and endcap geometry (from NOVA)
1661 //
1662 //cout << "Instantiating Pixel Detector" << endl;
1663 //cout << "Barrel Version " << this->PixelBarrelMajorVersion() << "." << this->PixelBarrelMinorVersion() << endl;
1664 //cout << "Endcap Version " << this->PixelEndcapMajorVersion() << "." << this->PixelEndcapMinorVersion() << endl;
1665}
1666
1671
1672
1674//
1675// Setting of Layer/Disk and Barrel/EndCap
1676//
1679{
1680 if(isBarrel() ) {
1681 if(i <= PixelBarrelNLayer()) {
1682 m_currentLD=i;
1683 } else {
1684 cout << "Layer set out of bounds, defaulting it to 0" << endl;
1685 m_currentLD = 0;
1686 std::cout<<" Current layer set to "<<i<<std::endl;
1687 }
1688 }
1689 if(isEndcap() ) {
1690 if (i<= PixelEndcapNDisk() ) {
1691 m_currentLD=i;
1692 } else {
1693 cout << "Disk set out of bounds, defaulting it to 0" << endl;
1694 m_currentLD = 0;
1695 std::cout<<" Current disk set to "<<i<<std::endl;
1696 }
1697 }
1698}
1699
1700
1701
1703 //cout << "Setting Barrel" << endl;
1704 m_BarrelEndcap = 0;
1705}
1707 m_BarrelEndcap = 1;
1708 //cout << "Setting Endcap" << endl;
1709}
1710
1711//
1712// Check if the current layer/disk has to be retrieved
1713// By default in MySQL all the three layers have to be retrieved
1714// If m_initialLayout is true we ignore NOVA for layer/disk 1.
1715// For initial layout layer=1 and disk=1 (2nd layer and disk) is missing.
1716//
1719 const std::string uscore("_");
1720 if(isBarrel()) {
1721 if (m_initialLayout && m_currentLD == 1) return false;
1722 std::string a=uscore+std::to_string(m_currentLD);
1723 return (*m_PixelBarrelGeneral)[0]->getInt("USELAYER"+a) == 1;
1724 }
1725 if(isEndcap() ) {
1726 if (m_initialLayout && m_currentLD == 1) return false;
1727 std::string a=uscore+std::to_string(m_currentLD);
1728 return (*m_PixelEndcapGeneral)[0]->getInt("USEDISK"+a) == 1;
1729 }
1730 return false;
1731}
1732
1733
1735 return m_BarrelEndcap == 0;
1736}
1738 return m_BarrelEndcap == 1;
1739 return false;
1740}
1741
1742//
1743// Calculate Thickness. This is used for the materials
1744// which thickness is given in % of r.l.
1745//
1747double OraclePixGeoManager::CalculateThickness(double tck,const string& mat) {
1748 GeoIntrusivePtr<const GeoMaterial> material{m_pMatMgr->getMaterial(mat)};
1749 double rl = material->getRadLength();
1750 return -1.*rl*tck/100.;
1751}
1752
1753//
1754// Si Boards Parameters:
1755//
1758{
1759 if(isBarrel()) return (*m_PixelModule)[m_currentLD]->getDouble("BOARDWIDTH")*Gaudi::Units::cm;
1760 if(isEndcap()) return (*m_PixelModule)[m_currentLD+3]->getDouble("BOARDWIDTH")*Gaudi::Units::cm;
1761 return 0.;
1762}
1764{
1765 if(isBarrel()) return (*m_PixelModule)[m_currentLD]->getDouble("BOARDLENGTH")*Gaudi::Units::cm;
1766 if(isEndcap()) return (*m_PixelModule)[m_currentLD+3]->getDouble("BOARDLENGTH")*Gaudi::Units::cm;
1767 return 0.;
1768}
1770{
1771 if (m_dc1Geometry && isBarrel() && (m_currentLD == 0)) {
1772 return 200*Gaudi::Units::micrometer;
1773 }
1774 if(isBarrel()) return (*m_PixelModule)[m_currentLD]->getDouble("BOARDTHICK")*Gaudi::Units::cm;
1775 if(isEndcap()) return (*m_PixelModule)[m_currentLD+3]->getDouble("BOARDTHICK")*Gaudi::Units::cm;
1776 return 0.;
1777}
1779{
1780 if(isEndcap()) return (*m_pxei)[m_currentLD]->getDouble("DRACTIVE")*Gaudi::Units::cm;
1781 if(isBarrel()) return (*m_pxbi)[m_currentLD]->getDouble("DZELEB")*Gaudi::Units::cm;
1782 return 0.;
1783}
1784
1785//
1786// Hybrid Parameters:
1787//
1790{
1791 if(isBarrel()) return (*m_PixelModule)[m_currentLD]->getDouble("HYBRIDWIDTH")*Gaudi::Units::cm;
1792 if(isEndcap()) return (*m_PixelModule)[m_currentLD+3]->getDouble("HYBRIDWIDTH")*Gaudi::Units::cm;
1793 return 0.;
1794}
1796{
1797 if(isBarrel()) return (*m_PixelModule)[m_currentLD]->getDouble("HYBRIDLENGTH")*Gaudi::Units::cm;
1798 if(isEndcap()) return (*m_PixelModule)[m_currentLD+3]->getDouble("HYBRIDLENGTH")*Gaudi::Units::cm;
1799 return 0.;
1800}
1802{
1803 double thick=0.;
1804 string mat;
1805 if(isBarrel()){
1806 // bad data name in db; here is worked around. Should be DXHYBR
1807 thick =(*m_PixelModule)[m_currentLD]->getDouble("HYBRIDTHICK");
1808 mat = "pix::Hybrid";
1809 }
1810 if(isEndcap()){
1811 thick =(*m_PixelModule)[m_currentLD+3]->getDouble("HYBRIDTHICK");
1812 mat = "std::Silicon";
1813 }
1814 // if it is negative is given in % of r.l.
1815 if(thick > 0.) {
1816 return thick*Gaudi::Units::cm;
1817 }
1818 return CalculateThickness(thick,mat);
1819
1820}
1821
1822//
1823// Chip Parameters:
1824//
1826
1828{
1829 if(isBarrel()) return (*m_PixelModule)[m_currentLD]->getDouble("CHIPWIDTH")*Gaudi::Units::cm;
1830 if(isEndcap()) return (*m_PixelModule)[m_currentLD+3]->getDouble("CHIPWIDTH")*Gaudi::Units::cm;
1831 return 0.;
1832}
1834{
1835 if(isBarrel())return (*m_PixelModule)[m_currentLD]->getDouble("CHIPLENGTH")*Gaudi::Units::cm;
1836 if(isEndcap())return (*m_PixelModule)[m_currentLD+3]->getDouble("CHIPLENGTH")*Gaudi::Units::cm;
1837 return 0.;
1838}
1840{
1841 if(isBarrel()) return (*m_PixelModule)[m_currentLD]->getDouble("CHIPGAP")*Gaudi::Units::cm;
1842 if(isEndcap()) return (*m_PixelModule)[m_currentLD+3]->getDouble("CHIPGAP")*Gaudi::Units::cm;
1843 return 0.;
1844}
1846 double thick=0.;
1847 string mat;
1848 if(isBarrel()){
1849 thick =(*m_PixelModule)[m_currentLD]->getDouble("CHIPTHICK");
1850 mat = "pix::Chip";
1851 }
1852 if(isEndcap()){
1853 thick =(*m_PixelModule)[m_currentLD+3]->getDouble("CHIPTHICK");
1854 mat = "std::Silicon";
1855 }
1856 // if it is negative is given in % of r.l.
1857 if(thick > 0.) {
1858 return thick*Gaudi::Units::cm;
1859 }
1860 return CalculateThickness(thick,mat);
1861
1862}
1863
1865//
1866// Pixel Disks carbon structure
1867//
1870 if(a == "Inner") {
1871 return (*m_PixelDisk)[m_currentLD]->getDouble("SUP1RMIN")*Gaudi::Units::cm;
1872 } else if (a == "Central") {
1873 return (*m_PixelDisk)[m_currentLD]->getDouble("SUP2RMIN")*Gaudi::Units::cm;
1874 }
1875 return (*m_PixelDisk)[m_currentLD]->getDouble("SUP3RMIN")*Gaudi::Units::cm;
1876}
1877
1879 if(a == "Inner") {
1880 return (*m_PixelDisk)[m_currentLD]->getDouble("SUP1RMAX")*Gaudi::Units::cm;
1881 } else if (a == "Central") {
1882 return (*m_PixelDisk)[m_currentLD]->getDouble("SUP2RMAX")*Gaudi::Units::cm;
1883 } else {
1884 return (*m_PixelDisk)[m_currentLD]->getDouble("SUP3RMAX")*Gaudi::Units::cm;
1885 }
1886}
1887
1889 double tck;
1890 int imat;
1891 string mat[4] = {"std::Berillia","std::Carbon","pix::ECSevices","pix::Disk"} ;
1892 if(a == "Inner") {
1893 tck = (*m_PixelDisk)[m_currentLD]->getDouble("SUP1THICK");
1894 imat =(*m_PixelDisk)[m_currentLD]->getInt("SUP1MAT")-1;
1895 } else if (a == "Central") {
1896 tck = (*m_PixelDisk)[m_currentLD]->getDouble("SUP2THICK");
1897 imat =(*m_PixelDisk)[m_currentLD]->getInt("SUP2MAT")-1;
1898 } else {
1899 tck = (*m_PixelDisk)[m_currentLD]->getDouble("SUP3THICK");
1900 imat =(*m_PixelDisk)[m_currentLD]->getInt("SUP3MAT")-1;
1901 }
1902 if(tck>0.) {
1903 return tck*Gaudi::Units::cm;
1904 }
1905 return CalculateThickness(tck,mat[imat]);
1906}
1908 string mat[4] = {"std::Berillia","std::Carbon","pix::ECSevices","pix::Disk"} ;
1909 int imat;
1910 if(a == "Inner") {
1911 imat = (*m_PixelDisk)[m_currentLD]->getInt("SUP1MAT")-1;
1912 } else if (a == "Central") {
1913 imat = (*m_PixelDisk)[m_currentLD]->getInt("SUP2MAT")-1;
1914 } else {
1915 imat = (*m_PixelDisk)[m_currentLD]->getInt("SUP3MAT")-1;
1916 }
1917 return mat[imat];
1918}
1919
1920
1922//
1923// Central Services (PBOI)
1924//
1926//
1927// This is complicated in the DB...
1928// If Rmin < 0 this means that the cylinder has to be placed only once
1929// So I return RMin with its sign, for further processing by the service
1930// methods.
1931// If RMax is <0 the thickness is given in % of r.l. which have to be
1932// calculated by the method calculatethickness
1933//
1934// If Zmin and Zmax have DIFFERENT sign, then the thickness is given in
1935// % of r.l....
1936//
1937
1939 if(isBarrel() ) {
1940 if(a == "Inside") return (*m_PixelBarrelGeneral)[0]->getInt("NFRAMEIN");
1941 if(a == "Outside") return (*m_PixelBarrelGeneral)[0]->getInt("NFRAMEOUT");
1942 }
1943 if(isEndcap() ) {
1944 if(a == "Inside") return (*m_PixelEndcapGeneral)[0]->getInt("NFRAMEIN");
1945 if(a == "Outside") return (*m_PixelEndcapGeneral)[0]->getInt("NFRAMEOUT");
1946 }
1947 return 0;
1948}
1949
1950double* OraclePixGeoManager::PixelServiceR(string_view a, int n) {
1951 double rmin=0.;
1952 double rmax=0.;
1953 double *r = new double[2]{};
1954 if(isBarrel()) {
1955 if(a == "Inside") {
1956 rmin = (*m_PixelBarrelService)[n]->getDouble("RIN");
1957 rmax = (*m_PixelBarrelService)[n]->getDouble("ROUT");
1958 }
1959 else {
1960 rmin = (*m_PixelBarrelService)[n+m_barrelInFrames]->getDouble("RIN");
1961 rmax = (*m_PixelBarrelService)[n+m_barrelInFrames]->getDouble("ROUT");
1962 }
1963 }
1964 if(isEndcap()) {
1965 if(a == "Inside") {
1966 rmin = (*m_PixelEndcapService)[n]->getDouble("RIN");
1967 rmax = (*m_PixelEndcapService)[n]->getDouble("ROUT");
1968 }
1969 else {
1970 rmin = (*m_PixelEndcapService)[n+m_endcapInFrames]->getDouble("RIN");
1971 rmax = (*m_PixelEndcapService)[n+m_endcapInFrames]->getDouble("ROUT");
1972 }
1973 }
1974 // If this is negative this is the thickness of the cyl in % of r.l.
1975 r[0] = rmin*Gaudi::Units::cm;
1976 if(rmax > 0) {
1977 r[1] = rmax*Gaudi::Units::cm;
1978 } else {
1979 string material = PixelServiceMaterial(a,n);
1980 r[1] = fabs(rmin*Gaudi::Units::cm)+CalculateThickness(rmax,material);
1981 }
1982 return r;
1983}
1984
1985
1986double* OraclePixGeoManager::PixelServiceZ(std::string_view a,int n) {
1987 double* z = new double[2]{};
1988 if(isBarrel()) {
1989 if(a == "Inside") {
1990 z[0] = (*m_PixelBarrelService)[n]->getDouble("ZIN");
1991 z[1] = (*m_PixelBarrelService)[n]->getDouble("ZOUT");
1992 }
1993 else {
1994 z[0] = (*m_PixelBarrelService)[n+m_barrelInFrames]->getDouble("ZIN");
1995 z[1] = (*m_PixelBarrelService)[n+m_barrelInFrames]->getDouble("ZOUT");
1996 }
1997 }
1998 if(isEndcap()) {
1999 if(a == "Inside") {
2000 z[0] = (*m_PixelEndcapService)[n]->getDouble("ZIN");
2001 z[1] = (*m_PixelEndcapService)[n]->getDouble("ZOUT");
2002 }
2003 else {
2004 z[0] = (*m_PixelEndcapService)[n+m_endcapInFrames]->getDouble("ZIN");
2005 z[1] = (*m_PixelEndcapService)[n+m_endcapInFrames]->getDouble("ZOUT");
2006 }
2007 }
2008 z[0] = z[0] *Gaudi::Units::cm;
2009 if(z[0]*(z[1]) > -0.000000001) { // same sign and z[0] > 0.
2010 z[1] = z[1] *Gaudi::Units::cm;
2011 } else {
2012 string material = PixelServiceMaterial(a,n);
2013 z[1] = z[0] * (1 + CalculateThickness(z[1],material)/fabs(z[0]));
2014 }
2015 if(isEndcap() && a == "Inside" ) { // Translate to the ecnter of EndCap
2016 double center = ((*m_PixelEndcapGeneral)[0]->getDouble("ZMAX")+(*m_PixelEndcapGeneral)[0]->getDouble("ZMIN"))/2.*Gaudi::Units::cm;
2017 z[0] = z[0]-center;
2018 z[1] = z[1]-center;
2019 }
2020 return z;
2021}
2022
2023
2025 if(isBarrel()) {
2026 if(a == "Inside") {return (*m_PixelBarrelService)[n]->getInt("LAYERNUM")-1;}
2027 else {return (*m_PixelBarrelService)[n+m_barrelInFrames]->getInt("LAYERNUM")-1;}
2028 }
2029 if(isEndcap()) {
2030 if(a == "Inside") {return (*m_PixelEndcapService)[n]->getInt("LAYERNUM")-1;}
2031 else {return (*m_PixelEndcapService)[n+m_endcapInFrames]->getInt("LAYERNUM")-1;}
2032 }
2033 return 0;
2034}
2035
2037 int imat;
2038 if(isBarrel()) {
2039 string mat[11] = {
2040 "std::Berillia",
2041 "std::Carbon",
2042 "pix::Services",
2043 "pix::Titanium",
2044 "pix::MatPP11",
2045 "pix::MatPP12",
2046 "pix::MatPP13",
2047 "pix::MatPP14",
2048 "pix::MatPP15",
2049 "pix::MatPP16",
2050 "pix::MatPP17"};
2051 if(a == "Inside") {imat = (*m_PixelBarrelService)[n]->getInt("MATERIAL")-1;}
2052 else {imat = (*m_PixelBarrelService)[n+m_barrelInFrames]->getInt("MATERIAL")-1;}
2053 return mat[imat];
2054 }
2055 if(isEndcap()) {
2056 string mat[4] = {"std::Berillia","std::Carbon","pix::ECServices","pix::Disk"};
2057 if(a == "Inside") {imat = (*m_PixelEndcapService)[n]->getInt("MATERIAL")-1;}
2058 else {imat =(*m_PixelEndcapService)[n+m_endcapInFrames]->getInt("MATERIAL")-1;}
2059 return mat[imat];
2060 }
2061 return "None";
2062}
2066
2070
2072 return m_initialLayout;
2073}
2074
2076 return m_dc1Geometry;
2077}
2078
2080 return m_alignable;
2081}
2082
2083
2085 if(m_pDDmgr == nullptr) {
2086 //
2087 // retrieve the pointer to the DD manager
2088 //
2089 StatusCode sc = m_pDetStore->retrieve(m_pDDmgr);
2090 if (sc.isFailure()) {
2091 std::cout << "Cannot retrieve PixelDetectorManager" << std::endl;
2092 }
2093 }
2094 return m_pDDmgr;
2095}
2096
2097
2098void OraclePixGeoManager::SetDetElementName(std::string_view name) {
2099 m_elementsObjectName.assign(name);
2100}
2101
2105
2106void OraclePixGeoManager::SetDesignName(std::string_view name) {
2107 m_designsObjectName.assign(name);
2108}
2109
2113
2115 m_barrelDesignName.assign(name);
2116}
2117
2121
2122void OraclePixGeoManager::SetEndcapModuleName(std::string_view name) {
2123 m_endcapDesignName.assign(name);
2124}
2125
2129
2130void OraclePixGeoManager::SetLayer0ModuleName(std::string_view name) {
2131 m_blayerDesignName.assign(name);
2132}
2133
2137
2138
2140{
2141 double tck = (*m_PixelStave)[0]->getDouble("SUPPORTTHICK");
2142 if( tck > 0.) {
2143 return tck*Gaudi::Units::cm;
2144 } else {
2145 return CalculateThickness(tck,"pix::Ladder");
2146 }
2147}
2148
2150{
2151 double tck = (*m_PixelDisk)[m_currentLD]->getDouble("CABLETHICK");
2152 if( tck > 0.) {
2153 return tck*Gaudi::Units::cm;
2154 } else {
2155 return CalculateThickness(tck,"pix::ECCables");
2156 }
2157}
2158
2160{
2161 double ActiveArea = DesignRPActiveArea();
2162 double GapRP = DesignGapRP();
2163 double pitchRP = DesignPitchRP(isBLayer);
2164 return static_cast<int>((ActiveArea - GapRP)/pitchRP + 0.5);
2165}
2166
2168{
2169 double ActiveArea = DesignZActiveArea();
2170 double GapZ = DesignGapZ();
2171 double pitchZ = DesignPitchZ(isBLayer);
2172 int CPR = DesignCircuitsPerRow();
2173 return static_cast<int>((ActiveArea - GapZ*CPR)/(CPR*pitchZ) + 0.5);
2174}
2175
2177{
2178 double ActiveArea = DesignRPActiveArea();
2179 double pitchRP = DesignPitchRP(isBLayer);
2180 return static_cast<int>((ActiveArea)/pitchRP + 0.5);
2181}
2182
2184{
2185 double ActiveArea = DesignZActiveArea();
2186 double GapZ = DesignGapZ();
2187 double pitchZ = DesignPitchZ(isBLayer) ;
2188 int CPR = DesignCircuitsPerRow();
2189 return static_cast<int>((ActiveArea - GapZ*CPR)/(CPR*pitchZ) + 0.5);
2190}
2191
2192 // Ganged Pixels
2194{
2195 return static_cast<int>((*m_pdch)[0]->getInt("NYCONNEC"));
2196}
2197
2199{
2200 const std::string a=std::string("_")+std::to_string(index);
2201 return static_cast<int>((*m_pdch)[0]->getInt("JYEMPTY"+a)) - 1;
2202}
2203
2205{
2206 const std::string a=std::string("_")+std::to_string(index);
2207 return static_cast<int>((*m_pdch)[0]->getInt("JYCONNEC"+a)) - 1;
2208}
2209
2210double OraclePixGeoManager::Voltage(bool isBLayer){
2211 // override B-layer voltage for DC1 geometry by
2212 // value in old DB (approx ratio of thicknesses (200/250 = 0.8)
2213 // 97.1*0.8 = 77.68. In Nova its 77.7.
2214 if (isBLayer && m_dc1Geometry) return 77.7*Gaudi::Units::volt;
2215 if(isBLayer) { return (*m_plor)[0]->getDouble("VOLTAGE")*Gaudi::Units::volt;}
2216 return (*m_plor)[1]->getDouble("VOLTAGE")*Gaudi::Units::volt;
2217}
2218
2220 if(isBLayer) { return (*m_plor)[0]->getDouble("TEMPC")*Gaudi::Units::kelvin+Gaudi::Units::STP_Temperature;}
2221 return (*m_plor)[1]->getDouble("TEMPC")*Gaudi::Units::kelvin+Gaudi::Units::STP_Temperature;
2222}
2223
2229
2230
2233{
2234 return m_commonItems;
2235}
2236
2237
2238void
2243
2244const PixelID *
2246{
2247 return dynamic_cast<const PixelID *>(m_commonItems->getIdHelper());
2248}
2249
2250
2251//---------------------------------------------------//
2252// //
2253// PixelGeometryManager //
2254// //
2255//---------------------------------------------------//
2256
2257using namespace std;
2258
2260 AthMessaging("PixelGeometryManager")
2261{
2262}
#define endmsg
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_DEBUG(x)
double length(const pvec &v)
static Double_t a
static Double_t sc
This is an Identifier helper class for the Pixel subdetector.
double angle(const GeoTrf::Vector2D &a, const GeoTrf::Vector2D &b)
const double width
#define z
#define max(a, b)
Definition cfImp.cxx:41
AthMessaging(IMessageSvc *msgSvc, const std::string &name)
Constructor.
This is a helper class to query the version tags from GeoModelSvc and determine the appropriate tag a...
const std::string & tag() const
Return version tag.
const std::string & node() const
Return the version node.
virtual GeoVPhysVol * Build() override
virtual GeoVPhysVol * Build() override
virtual GeoVPhysVol * Build() override
GeoPixelDisk(InDetDD::PixelDetectorManager *ddmgr, PixelGeometryManager *mgr, GeoModelIO::ReadGeoModel *sqliteReader, std::shared_ptr< std::map< std::string, GeoFullPhysVol * > > mapFPV, std::shared_ptr< std::map< std::string, GeoAlignableTransform * > > mapAX)
virtual GeoVPhysVol * Build() override
PixelGeometryManager * m_gmt_mgr
InDetMaterialManager * m_mat_mgr
Dedicated detector manager extending the functionality of the SiDetectorManager with dedicated pixel ...
virtual void addAlignableTransform(int level, const Identifier &id, GeoAlignableTransform *xf, const GeoVFullPhysVol *child)
Add alignable transforms.
Tree structure to find the position, index or pitch of a pixel on a semi-regular grid The grid is con...
Helper class to concentrate common items, such as the pointer to the IdHelper, the lorentzAngle tool ...
const SiNumerology & numerology() const
Access Numerology.
void setNumRingsForDisk(int disk, int nRings)
void setNumDisks(int nDisks)
void setNumPhiModulesForDiskRing(int disk, int ring, int nPhiModules)
void setNumPhiModulesForLayer(int layer, int nPhiModules)
void setNumEtaModulesForLayer(int layer, int nEtaModules)
const GeoMaterial * getMaterial(std::string_view materialName)
Get material. First looks for locally defined material and if not found looks in GeoModel material ma...
virtual GeoVPhysVol * Build() override
GeoPixelDiskSupports(InDetDD::PixelDetectorManager *ddmgr, PixelGeometryManager *mgr)
std::vector< std::string > m_material
virtual GeoVPhysVol * Build() override
GeoIntrusivePtr< GeoLogVol > m_theDisk
GeoPixelECCable(InDetDD::PixelDetectorManager *ddmgr, PixelGeometryManager *mgr)
virtual GeoVPhysVol * Build() override
GeoIntrusivePtr< GeoLogVol > m_theECCable
virtual GeoVPhysVol * Build() override
virtual GeoVPhysVol * Build() override
virtual GeoVPhysVol * Build() override
virtual GeoVPhysVol * Build() override
GeoIntrusivePtr< GeoLogVol > m_theLadder
GeoPixelLadder(InDetDD::PixelDetectorManager *ddmgr, PixelGeometryManager *mgr, GeoPixelSiCrystal &theSensor)
virtual GeoVPhysVol * Build() override
virtual GeoVPhysVol * Build() override
GeoIntrusivePtr< GeoLogVol > m_theModule
virtual GeoVPhysVol * Build() override
GeoPixelModule(InDetDD::PixelDetectorManager *ddmgr, PixelGeometryManager *mgr, GeoPixelSiCrystal &theSensor)
std::vector< std::string > m_material
void initialize(const std::string &)
GeoPixelServices(InDetDD::PixelDetectorManager *ddmgr, PixelGeometryManager *mgr, const std::string &)
virtual GeoVPhysVol * Build() override
virtual GeoVPhysVol * Build() override
GeoPixelSiCrystal(InDetDD::PixelDetectorManager *ddmgr, PixelGeometryManager *mgr, bool isBLayer)
const InDetDD::SiDetectorDesign * m_design
virtual GeoVPhysVol * Build() override
GeoIntrusivePtr< GeoLogVol > m_theSubDisk
GeoPixelSubDisk(InDetDD::PixelDetectorManager *ddmgr, PixelGeometryManager *mgr, GeoPixelSiCrystal &theSensor)
GeoIntrusivePtr< GeoLogVol > m_theBox
virtual GeoVPhysVol * Build() override
GeoPixelTubeCables(InDetDD::PixelDetectorManager *ddmgr, PixelGeometryManager *mgr)
StoredMaterialManager * m_mat_mgr
PixelGeometryManager * m_gmt_mgr
GeoVPixelFactory(InDetDD::PixelDetectorManager *ddmgr, PixelGeometryManager *mgr)
InDetDD::PixelDetectorManager * m_DDmgr
virtual double DesignPitchZ(bool isBLayer) override
virtual double Voltage(bool isBLayer) override
virtual double PixelLadderThickness() override
virtual double DesignRPActiveArea() override
virtual int DesignDiodeColumnsPerCircuit(bool isBLayer) override
const PixelID * getIdHelper() override
virtual void SetCurrentLD(int i) override
virtual double PixelChipWidth() override
virtual void SetDetElementName(std::string_view) override
virtual void SetDesignName(std::string_view) override
virtual double PixelChipLength() override
virtual std::string GetDetElementName() override
virtual void SetEndcapModuleName(std::string_view) override
virtual double PixelHybridThickness() override
virtual double DesignPitchRP(bool isBLayer) override
virtual int DesignCellColumnsPerCircuit(bool isBLayer) override
virtual void SetBarrelModuleName(std::string_view) override
virtual double PixelBoardThickness() override
virtual double PixelChipThickness() override
virtual double DesignGapRP() override
virtual double PixelBoardWidth() override
virtual void setCommonItems(InDetDD::SiCommonItems *commonItems) override
virtual int DesignCircuitsPerRow() override
virtual std::string GetLayer0ModuleName() override
virtual StoredMaterialManager * getMaterialManager() override
virtual double PixelBoardLength() override
virtual int EmptyRowConnections(int index) override
virtual std::string PixelServiceMaterial(std::string_view, int) override
virtual bool DC1Geometry() const override
virtual double PixelECCarbonRMax(std::string) override
virtual std::string GetEndcapModuleName() override
virtual int PixelBarrelNLayer() override
virtual int PixelServiceLD(std::string_view, int) override
virtual double PixelECCarbonRMin(std::string) override
virtual std::string GetBarrelModuleName() override
virtual int DesignCellRowsPerCircuit(bool isBLayer) override
double CalculateThickness(double, const std::string &)
virtual void SetLayer0ModuleName(std::string_view) override
virtual double * PixelServiceZ(std::string_view, int) override
virtual bool InitialLayout() const override
virtual double * PixelServiceR(std::string_view, int) override
virtual double PixelHybridLength() override
InDetDD::PixelDetectorManager * m_pDDmgr
virtual bool G3CompatibleDigits() const override
virtual double DesignGapZ() override
InDetDD::SiCommonItems * m_commonItems
virtual double PixelECCarbonThickness(std::string) override
virtual double PixelECCablesThickness() override
virtual double PixelBoardActiveLen() override
virtual InDetDD::SiCommonItems * commonItems() override
virtual int EmptyRows(int index) override
virtual double Temperature(bool isBLayer) override
virtual double PixelHybridWidth() override
virtual std::string PixelECCarbonMaterial(std::string) override
virtual std::string GetDesignName() override
virtual InDetDD::PixelDetectorManager * GetPixelDDManager() override
virtual int DesignDiodeRowsPerCircuit(bool isBLayer) override
virtual double DesignZActiveArea() override
virtual int PixelServiceNFrame(std::string_view) override
virtual bool Alignable() const override
virtual double PixelChipLength()=0
virtual void SetPhi(int phi)=0
virtual double PixelHybridThickness()=0
virtual double PixelModuleAngle()=0
virtual double PixelEndcapZMax()=0
virtual double PixelChipWidth()=0
virtual double PixelChipThickness()=0
virtual double PixelModuleDrDistance()=0
virtual double PixelCableWidth()=0
virtual double PixelModuleAngleSign(int)=0
virtual double PixelDiskPosition()=0
virtual double PixelECCablesDistance()=0
virtual double PixelLadderHalfLength()=0
virtual double PixelEndcapZMin()=0
virtual double PixelModulePosition(int)=0
virtual double PixelEndcapRMax()=0
virtual const PixelID * getIdHelper()=0
virtual double PixelBoardThickness()=0
virtual double PixelEndcapRMin()=0
virtual void SetEta(int eta)=0
virtual double PixelLadderTilt()=0
virtual double PixelModuleShiftFlag(int)=0
virtual void SetCurrentLD(int i)=0
virtual double PixelLayerRadius()=0
This is an Identifier helper class for the Pixel subdetector.
Definition PixelID.h:69
Identifier wafer_id(int barrel_ec, int layer_disk, int phi_module, int eta_module) const
For a single crystal.
Definition PixelID.h:355
This class holds one or more material managers and makes them storeable, under StoreGate.
virtual const GeoMaterial * getMaterial(std::string_view name)=0
int r
Definition globals.cxx:22
phimod(flags, cells_name, *args, **kw)
PixelDiodeTree makePixelDiodeTree(T_MsgParent *gmt_mgr, InDetDD::PixelReadoutTechnology readoutTechnology, const std::array< int, kNDirections > &circuits, const std::array< int, kNDirections > &dimPerCircuit, const std::array< std::array< double, kNDirections >, kNPixelLocations > &pitch, FENumbering fe_numbering)
Definition index.py:1
STL namespace.
void initialize()