ATLAS Offline Software
Loading...
Searching...
No Matches
PixelDetectorDC1DC2.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5// 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"
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(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(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
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
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
2099 m_elementsObjectName = name;
2100}
2101
2105
2107 m_designsObjectName = name;
2108}
2109
2113
2115 m_barrelDesignName = name;
2116}
2117
2121
2123 m_endcapDesignName = name;
2124}
2125
2129
2131 m_blayerDesignName = 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
constexpr int pow(int base, int exp) noexcept
#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(const std::string &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 int PixelServiceNFrame(std::string) override
virtual double DesignRPActiveArea() override
virtual void SetEndcapModuleName(std::string) override
virtual int DesignDiodeColumnsPerCircuit(bool isBLayer) override
const PixelID * getIdHelper() override
virtual void SetCurrentLD(int i) override
virtual double PixelChipWidth() override
virtual void SetLayer0ModuleName(std::string) override
virtual double PixelChipLength() override
virtual std::string GetDetElementName() override
virtual double PixelHybridThickness() override
virtual double DesignPitchRP(bool isBLayer) override
virtual int DesignCellColumnsPerCircuit(bool isBLayer) 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 bool DC1Geometry() const override
virtual std::string PixelServiceMaterial(std::string, int) override
virtual double PixelECCarbonRMax(std::string) override
virtual std::string GetEndcapModuleName() override
virtual int PixelBarrelNLayer() 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 int PixelServiceLD(std::string, int) override
virtual bool InitialLayout() const override
virtual void SetDesignName(std::string) override
virtual double PixelHybridLength() override
virtual double * PixelServiceZ(std::string, int) 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 * PixelServiceR(std::string, int) 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 void SetDetElementName(std::string) 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 void SetBarrelModuleName(std::string) override
virtual double DesignZActiveArea() 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:67
Identifier wafer_id(int barrel_ec, int layer_disk, int phi_module, int eta_module) const
For a single crystal.
Definition PixelID.h:360
This class holds one or more material managers and makes them storeable, under StoreGate.
virtual const GeoMaterial * getMaterial(const std::string &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()