ATLAS Offline Software
Loading...
Searching...
No Matches
TRTDetectorFactory_Lite.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
7
17#include "GeoModelRead/ReadGeoModel.h"
18#include "ArrayFunction.h"
20#include "GeoModelKernel/GeoPhysVol.h"
21#include "GeoModelKernel/GeoFullPhysVol.h"
22#include "GeoModelKernel/GeoAlignableTransform.h"
23#include "GeoModelKernel/GeoCountVolAndSTAction.h"
24#include "GeoModelKernel/GeoAccessVolAndSTAction.h"
25#include "GeoModelKernel/GeoDefinitions.h"
26#include "GeoModelKernel/GeoVolumeCursor.h"
27#include "GeoModelKernel/Units.h"
28#include "GeoGenericFunctions/AbsFunction.h"
29#include "GeoGenericFunctions/Variable.h"
30#include "GeoGenericFunctions/Sin.h"
31#include "GeoGenericFunctions/Cos.h"
36
37#include <vector>
38#include <cmath>
39
40//TK: get rid of these and use GeoGenfun:: and GeoXF:: instead
41using namespace GeoGenfun;
42using namespace GeoXF;
43
44
46//
47TRTDetectorFactory_Lite::TRTDetectorFactory_Lite(GeoModelIO::ReadGeoModel *sqliteReader,
48 InDetDD::AthenaComps * athenaComps,
49 std::unique_ptr<const TRTStrawStatusAccessor> statusAccessor,
50 bool useOldActiveGasMixture,
51 bool DC2CompatibleBarrelCoordinates,
52 bool alignable,
53 bool useDynamicAlignmentFolders)
54 : InDetDD::DetectorFactoryBase(athenaComps),
55 m_sqliteReader (sqliteReader),
56 m_statusAccessor(std::move(statusAccessor)),
57 m_useOldActiveGasMixture(useOldActiveGasMixture),
58 m_DC2CompatibleBarrelCoordinates(DC2CompatibleBarrelCoordinates),
59 m_alignable(alignable),
60 m_useDynamicAlignFolders(useDynamicAlignmentFolders)
61{
62}
63
65//
66// The method that actually returns the TRT_DetectorManager, which was created
67// and filled by the create() method
68//
70{
71 //TK: Maybe check that m_detectorManager!=0 ?
72 return m_detectorManager;
73}
74
75
76
77
79//
80// This is where the actual building of the geometry is performed.
81//
82// The purpose of this is to create a new TRT_DetectorManager and fill it with
83// all the information relevant for detector description.
84//
85// The TRT_DetectorManager itself, along with helper classes, descriptors, etc.
86// is located in InDetDetDescr/InDetReadoutGeometry.
87//
89{
90 // Here we build materials by hand. This awaits updates to GeoModelIO which would allow to retreive materials from
91 // the database. At that point we can remove the manual creation of materials.
92
93 // Make two kinds of Gas
94 GeoElement *carbon = new GeoElement("Carbon","C",6,12.0112*GeoModelKernelUnits::gram/GeoModelKernelUnits::mole);
95 GeoElement *oxygen = new GeoElement("Oxygen","O",8,15.9994*GeoModelKernelUnits::gram/GeoModelKernelUnits::mole);
96 GeoElement *argon = new GeoElement("Argon","Ar",18,39.948*GeoModelKernelUnits::gram/GeoModelKernelUnits::mole);
97 GeoElement *xenon = new GeoElement("Xenon","Xe",54,131.3*GeoModelKernelUnits::gram/GeoModelKernelUnits::mole);
98
99 GeoMaterial *trtCO2 = new GeoMaterial("trt::CO2", 0.001842*GeoModelKernelUnits::gram / GeoModelKernelUnits::cm3);
100 trtCO2->add(carbon,1);
101 trtCO2->add(oxygen,2);
102 trtCO2->lock();
103
104
105 GeoMaterial *trtO2 = new GeoMaterial("trt::O2", 0.001334*GeoModelKernelUnits::gram / GeoModelKernelUnits::cm3);
106 trtO2->add(oxygen,1);
107 trtO2->lock();
108
109 GeoMaterial *trtArgon = new GeoMaterial("trt::Argon", 0.001662*GeoModelKernelUnits::gram / GeoModelKernelUnits::cm3);
110 trtArgon->add(argon,1);
111 trtArgon->lock();
112
113 GeoMaterial *trtXenon = new GeoMaterial("trt::Xenon", 0.005485*GeoModelKernelUnits::gram / GeoModelKernelUnits::cm3);
114 trtXenon->add(xenon,1);
115 trtXenon->lock();
116
117 GeoMaterial *argonGas = new GeoMaterial("trt::ArCO2O2",0.00165878*GeoModelKernelUnits::gram / GeoModelKernelUnits::cm3);
118 argonGas->add(trtArgon,0.7);
119 argonGas->add(trtCO2,0.27);
120 argonGas->add(trtO2,0.03);
121 argonGas->lock();
122
123 GeoMaterial *xenonGas = new GeoMaterial("trt::XeCO2O2",0.00437686*GeoModelKernelUnits::gram / GeoModelKernelUnits::cm3);
124 xenonGas->add(trtXenon,0.7);
125 xenonGas->add(trtCO2,0.27);
126 xenonGas->add(trtO2,0.03);
127 xenonGas->lock();
128
129 m_argonGas=argonGas;
130 m_xenonGas=xenonGas;
131
132 std::map<std::string, GeoFullPhysVol*> mapFPV = m_sqliteReader->getPublishedNodes<std::string, GeoFullPhysVol*>("TRT");
133 std::map<std::string, GeoAlignableTransform*> mapAX = m_sqliteReader->getPublishedNodes<std::string, GeoAlignableTransform*>("TRT");
134
135 // The top level volumes
136 GeoFullPhysVol *pBarrelVol = mapFPV["TRTBarrel"];
137 GeoFullPhysVol *pEndCapABPlus = mapFPV["TRTEndCapABPlus"];
138 GeoFullPhysVol *pEndCapCPlus = mapFPV["TRTEndCapCPlus"];
139 GeoFullPhysVol *pEndCapABMinus = mapFPV["TRTEndCapABMinus"];
140 GeoFullPhysVol *pEndCapCMinus = mapFPV["TRTEndCapCPlus"];;
141
142
143
144 // Create a new detectormanager.
146
147 //---------------------- Initialize the parameter interface ------------------------//
148
149 ATH_MSG_DEBUG( " Getting primary numbers from the Detector Description Database " );
151 m_data.reset(parameterInterface);
152
153
154 IRDBAccessSvc* iAccessSvc = rdbAccessSvc();
155
156
157 std::vector<GeoTrf::Transform3D> shellPosVec;
158 IRDBRecordset_ptr trtShellPosVecRecordSet = iAccessSvc->getRecordsetPtr("TRTShellPosVec","","","");
159 for (size_t r=0;r<trtShellPosVecRecordSet->size();r++) {
160 const IRDBRecord * trtShellPosVecRecord = (*trtShellPosVecRecordSet)[r];
161 double xx=trtShellPosVecRecord->getDouble("xx");
162 double xy=trtShellPosVecRecord->getDouble("xy");
163 double xz=trtShellPosVecRecord->getDouble("xz");
164
165 double yx=trtShellPosVecRecord->getDouble("yx");
166 double yy=trtShellPosVecRecord->getDouble("yy");
167 double yz=trtShellPosVecRecord->getDouble("yz");
168
169 double zx=trtShellPosVecRecord->getDouble("zx");
170 double zy=trtShellPosVecRecord->getDouble("zy");
171 double zz=trtShellPosVecRecord->getDouble("zz");
172
173 double dx=trtShellPosVecRecord->getDouble("dx");
174 double dy=trtShellPosVecRecord->getDouble("dy");
175 double dz=trtShellPosVecRecord->getDouble("dz");
176 Eigen::Matrix4d M;
177 M(0,0)=xx; M(0,1)=xy; M(0,2)=xz; M(0,3)=dx;
178 M(1,0)=yx; M(1,1)=yy; M(1,2)=yz; M(1,3)=dy;
179 M(2,0)=zx; M(2,1)=zy; M(2,2)=zz; M(2,3)=dz;
180 M(3,0)= 0; M(3,1)= 0; M(3,2)= 0; M(3,3)=1;
181 GeoTrf::Transform3D T;
182 T.matrix()=M;
183 shellPosVec.push_back(T);
184 }
185
186 //---------------------- Initialize ID Helper ------------------------------------//
187 const TRT_ID *idHelper = nullptr;
188
189 if (detStore()->retrieve(idHelper, "TRT_ID").isFailure()) {
190 ATH_MSG_ERROR( "Could not retrieve TRT ID Helper");
191 }
192
193 m_detectorManager->setIdHelper(idHelper,false);
194
195 //---------------------- Set and Print Version Information ------------------------------------//
196
197 //Set active gas type information.
200
201 // Set Version information
202 // Some of these get overwritten for new configurations.
203 std::string versionTag = m_data->versionTag;
204 std::string versionName = "DC2";
205 std::string layout = "Final";
206 std::string description = "DC2 Geometry";
207 int versionMajorNumber = 2;
208 int versionMinorNumber = 1;
209 int versionPatchNumber = 0;
210
211 if (m_data->initialLayout) layout = "Initial";
212 //In principle we dont need to let the minor number reflect the
213 //gastype anymore, but it doesn't hurt:
214 if (m_useOldActiveGasMixture) versionMinorNumber = 0;
216 versionMajorNumber = 3;
217 versionName = "Rome";
218 description = "Geometry for Rome 2005";
219 }
220
221 if (m_data->isCosmicRun) {
222 layout = "SR1";
223 description = "Geometry for SR1";
224 }
225
226
227 // If new configuration we get the version information from the database.
228 // The version numbers can be incremented as one sees fit.
229 // In principle they should be changed whenever there are any code changes.
230 if (!m_data->oldConfiguration) {
231 versionName = m_data->versionName;
232 layout = m_data->layout;
233 description = m_data->versionDescription;
234 versionMajorNumber = 4;
235 versionMinorNumber = 1;
236 versionPatchNumber = 1;
237 }
238
239 InDetDD::Version version(versionTag,
240 versionName,
241 layout,
243 versionMajorNumber,
244 versionMinorNumber,
245 versionPatchNumber);
246
247 m_detectorManager->setVersion(version);
248
249
250 // Print version information.
251 ATH_MSG_INFO( "In TRT Detector Factory Lite" );
252 ATH_MSG_INFO( " " << version.fullDescription() );
253
254
255 //---------- Alignmnent and Conditions -----------//
256 // Register the channels for alignment constants
257 // and the level corresponding to the channel.
258 // Not the levels are an internal definition . They are not the same as
259 // the usual alignment levels
260 const int AlignmentLevelSubWheel = 1; // Level 2 in endcap. Not used in barrel
261 const int AlignmentLevelModule = 2; // Level 2 in barrel. Deprecated (wheel level) in endcap.
262 const int AlignmentLevelTop = 3; // Level 1
263
264 if (m_alignable) {
265
267 m_detectorManager->addAlignFolderType(InDetDD::static_run1);
268 m_detectorManager->addFolder("/TRT/Align");
269 m_detectorManager->addChannel("/TRT/Align/TRT", AlignmentLevelTop, InDetDD::global);
270
271 if (pBarrelVol) {
272 m_detectorManager->addChannel("/TRT/Align/B0", AlignmentLevelModule, InDetDD::global);
273 m_detectorManager->addChannel("/TRT/Align/B1", AlignmentLevelModule, InDetDD::global);
274 m_detectorManager->addChannel("/TRT/Align/B2", AlignmentLevelModule, InDetDD::global);
275 }
276 if (pEndCapABPlus) { // EndcapA
277 m_detectorManager->addChannel("/TRT/Align/L2A", AlignmentLevelSubWheel, InDetDD::global);
278 }
279 if (pEndCapABMinus) {// EndcapC
280 m_detectorManager->addChannel("/TRT/Align/L2C", AlignmentLevelSubWheel, InDetDD::global);
281 }
282 }
283
284 else {
286
287 m_detectorManager->addGlobalFolder("/TRT/AlignL1/TRT");
288 m_detectorManager->addChannel("/TRT/AlignL1/TRT", AlignmentLevelTop, InDetDD::global);
289 m_detectorManager->addFolder("/TRT/AlignL2");
290
291 if (pBarrelVol) {
292 m_detectorManager->addChannel("/TRT/AlignL2/B0", AlignmentLevelModule, InDetDD::global);
293 m_detectorManager->addChannel("/TRT/AlignL2/B1", AlignmentLevelModule, InDetDD::global);
294 m_detectorManager->addChannel("/TRT/AlignL2/B2", AlignmentLevelModule, InDetDD::global);
295 }
296
297 if (pEndCapABPlus) { // EndcapA
298 m_detectorManager->addChannel("/TRT/AlignL2/L2A", AlignmentLevelSubWheel, InDetDD::global);
299 }
300 if (pEndCapABMinus) {// EndcapC
301 m_detectorManager->addChannel("/TRT/AlignL2/L2C", AlignmentLevelSubWheel, InDetDD::global);
302 }
303 }
304
305 // Unchanged in Run1 and new Run2 schema
306 m_detectorManager->addSpecialFolder("/TRT/Calib/DX");
307 }
308
309
310
311 //Uncomment for testing:
312 // m_data->ShowValues();
313
314 //----------------------Initialize the numerology------------------------//
315
316 for (unsigned int m=0;m<m_data->nBarrelRings;m++) {
317 m_detectorManager->getNumerology()->setNBarrelLayers(m, m_data->barrelNumberOfStrawLayersInModule[m]);
318 }
319
320 m_detectorManager->getNumerology()->setNBarrelRings(m_data->nBarrelRings);
321 //Note: This next line is now consistent with TRT_TestBeamDetDescr.
322 m_detectorManager->getNumerology()->setNBarrelPhi(m_data->nBarrelModulesUsed);
323
324 unsigned int nEndcapWheels = 0;
325 if (pEndCapABPlus||pEndCapABMinus) nEndcapWheels += m_data->endcapNumberOfAWheels + m_data->endcapNumberOfBWheels;
326 if (pEndCapCPlus||pEndCapCMinus) nEndcapWheels += m_data->endcapNumberOfCWheels;
327
328 m_detectorManager->getNumerology()->setNEndcapWheels(nEndcapWheels);
329 m_detectorManager->getNumerology()->setNEndcapPhi(m_data->nEndcapPhi);
330
331 for (unsigned int w=0;w<m_detectorManager->getNumerology()->getNEndcapWheels();w++) {
332 unsigned int nlayers;
333 if ( w < m_data->endcapNumberOfAWheels )
334 nlayers = m_data->endCapNumberOfStrawLayersPerWheelA;
335 else if ( w < ( m_data->endcapNumberOfAWheels + m_data->endcapNumberOfBWheels ) )
336 nlayers = m_data->endCapNumberOfStrawLayersPerWheelB;
337 else
338 nlayers = m_data->endCapNumberOfStrawLayersPerWheelC;
339 m_detectorManager->getNumerology()->setNEndcapLayers(w, nlayers ) ;
340 }
341
342
343 //
344 // Barrel volume:
345 //
346
347 if (pBarrelVol) {
348
349 ATH_MSG_DEBUG( "Virtual TRT Barrel volume defined by RMin = "<<m_data->virtualBarrelInnerRadius
350 <<", Rmax = "<<m_data->virtualBarrelOuterRadius<<" Zmax = "<<m_data->virtualBarrelVolumeLength );
351
352 // Common Endcap volumes (one for forward, one for backward):
353 //GeoPhysVol *pCommonEndcapVolume[2];
354
355 GeoAlignableTransform * barrelTransform = mapAX["TRTBarrel"];
356
357 m_detectorManager->addTreeTop(pBarrelVol);
358 // Use barrel_ec_id = -1 (+ve and -ve barrel is treated as one alignable object)
359 Identifier id = idHelper->barrel_ec_id(-1);
360 m_detectorManager->addAlignableTransform(AlignmentLevelTop, id, barrelTransform, pBarrelVol); // global if other selected
361
362 }
363
364 if (pEndCapABPlus) {
365
366 GeoAlignableTransform * transform = mapAX["TRTEndCapABPlus"];
367
368 m_detectorManager->addTreeTop(pEndCapABPlus);
369 Identifier id = idHelper->barrel_ec_id(2);
370 m_detectorManager->addAlignableTransform(AlignmentLevelTop, id, transform, pEndCapABPlus); // global if other selected
371 }
372
373 if (pEndCapABMinus) {
374
375 GeoAlignableTransform * transform = mapAX["TRTEndCapABMinus"];
376
377 m_detectorManager->addTreeTop(pEndCapABMinus);
378 Identifier id = idHelper->barrel_ec_id(-2);
379 m_detectorManager->addAlignableTransform(AlignmentLevelTop, id, transform, pEndCapABMinus); // global if other selected
380 }
381
382 if (pEndCapCPlus) {
383 m_detectorManager->addTreeTop(pEndCapCPlus);
384 }
385 if (pEndCapCMinus) {
386 m_detectorManager->addTreeTop(pEndCapCMinus);
387 }
388 // Pointers to the Endcap volumes (index 0: for forward, index 1: for backward):
389 GeoFullPhysVol *pCommonEndcapAB[]={pEndCapABPlus,pEndCapABMinus};
390 GeoFullPhysVol *pCommonEndcapC[]={pEndCapCPlus,pEndCapCMinus};
391 //-----------------------------------------------------------------------//
392 // //
393 // Barrel //
394 // //
395 //-----------------------------------------------------------------------//
396
397
398 if (pBarrelVol) {
399
400
401 //-----------------------------------------------------------------------//
402 // //
403 // Barrel Modules //
404 // //
405 //-----------------------------------------------------------------------//
406
407 std::vector<InDetDD::TRT_BarrelDescriptor *> bDescriptor;
408
409 // Create some shared stuff to stick into each module.
410
411 // The barrel straw (including the "hole" in the radiator around it):
412 double activeGasZPositionNormalStraws= activeGasZPosition();
413 // The straws in the inner layers of module A have a large dead region, and are thus different.
414 double activeGasZPositionStrawsWithLargeDeadRegion= activeGasZPosition(true);
415
416 // The modules themselves.
417 for (size_t iABC=0;iABC<m_data->nBarrelRings;iABC++) {
418
419 GeoTrf::Transform3D shellPosition=shellPosVec[iABC];
420
421 //----------------------------------------------------------------------------------------------------------------
422 // Parameterize all of the straws and put them within the radiator.
423
424 // Figure out how many straws have a large dead region
425 size_t nStrawsWithLargeDeadRegion = 0;
426 if (iABC==0) {
427 for (size_t iLayer = 0; iLayer<m_data->barrelNumberOfLayersWithLargeDeadRegion; iLayer++) {
428 nStrawsWithLargeDeadRegion += m_data->barrelNumberOfStrawsInStrawLayer[iABC][iLayer];
429 }
430 }
431
432 // Generators:
433 GeoTrf::TranslateX3D Xx(1.0);
434 GeoTrf::TranslateY3D Xy(1.0);
435
436 GENFUNCTION fx = ArrayFunction(&m_data->strawXPosition[iABC][0+nStrawsWithLargeDeadRegion],
437 &m_data->strawXPosition[iABC][0]+m_data->barrelNumberOfStrawsInModule[iABC]);
438 //TK: why ..[0]+n and not ..[n] ?
439 GENFUNCTION fy = ArrayFunction(&m_data->strawYPosition[iABC][0+nStrawsWithLargeDeadRegion],
440 &m_data->strawYPosition[iABC][0]+m_data->barrelNumberOfStrawsInModule[iABC]);
441 TRANSFUNCTION tx1 = Pow(Xx,fx)*Pow(Xy,fy);
442
443 //TK: Quick fix, might waste a few KB of memory.
444 //TK: only use when iABC==0
445 GENFUNCTION fxAll = ArrayFunction(&m_data->strawXPosition[iABC][0], &m_data->strawXPosition[iABC][0]+m_data->barrelNumberOfStrawsInModule[iABC]);
446 GENFUNCTION fyAll = ArrayFunction(&m_data->strawYPosition[iABC][0], &m_data->strawYPosition[iABC][0]+m_data->barrelNumberOfStrawsInModule[iABC]);
447 TRANSFUNCTION tx1All = Pow(Xx,fxAll)*Pow(Xy,fyAll);
448
449
451 //Calculation of needed transforms
452 //First get the global and local positions of the two alignment straws:
453 //USE HEP2VECTORS!!!
454
455 GeoTrf::Vector3D Align1Global(m_data->barrelXOfFirstGlobalAlignmentStraw[iABC], m_data->barrelYOfFirstGlobalAlignmentStraw[iABC], 0);
456 GeoTrf::Vector3D Align2Global(m_data->barrelXOfSecondGlobalAlignmentStraw[iABC], m_data->barrelYOfSecondGlobalAlignmentStraw[iABC],0);
457 GeoTrf::Vector3D Align1Local(m_data->strawXPosition[iABC][0],m_data->strawYPosition[iABC][0],0);
458 GeoTrf::Vector3D Align2Local(m_data->strawXPosition[iABC][m_data->barrelIndexOfSecondGlobalAlignmentStraw[iABC]],
459 m_data->strawYPosition[iABC][m_data->barrelIndexOfSecondGlobalAlignmentStraw[iABC]],0);
460
461 //We need to make first a translation which puts the first alignment straw into place:
462
463 //And we need to make a rotation which puts the second one on its position:
464
465 GeoTrf::Vector2D local12((Align2Local - Align1Local).x(),(Align2Local - Align1Local).y());
466 GeoTrf::Vector2D global12((Align2Global - Align1Global).x(),(Align2Global - Align1Global).y());
467 double zrotang = global12.phi()-local12.phi();
468
469 //Here we combine these two into a GeoTrf::Transform3D:
470
471 GeoTrf::Transform3D absStrawXForm = GeoTrf::Translate3D(Align1Global.x(),Align1Global.y(),Align1Global.z())
472 *GeoTrf::RotateZ3D( zrotang )
473 *GeoTrf::Translate3D(-Align1Local.x(),-Align1Local.y(),-Align1Local.z());
474
475 //
477
478 //Why not use radiator instead of shell?
479 TRANSFUNCTION tx2=shellPosition.inverse()*absStrawXForm*tx1;
480 TRANSFUNCTION tx2All=shellPosition.inverse()*absStrawXForm*tx1All;
481 if (iABC==0) {
482 //TK: move rest of ...All stuff here?
483 m_detectorManager->setBarrelTransformField(iABC,tx2All.clone());
484 } else {
485 m_detectorManager->setBarrelTransformField(iABC,tx2.clone());
486 }
487
488
489 // Adds one straw from each layer (reformulate..) (should be done via m_data from database)
490 double oldx=-999*GeoModelKernelUnits::cm, oldz=-999*GeoModelKernelUnits::cm;
491 unsigned int c=0;
492 size_t iLayer=0;
493 while (c< m_data->barrelNumberOfStrawsInModule[iABC] ) {
494
495 GeoTrf::Vector3D p(0,0,0);
496 if (iABC==0)
497 p = tx2All(c)*p;
498 else
499 p = tx2(c)*p;
500
501 double x = p.x();
502 double z = p.z();
503
504 //TK: use arrays!! update this...
505 if (sqrt((x-oldx)*(x-oldx)+ (z-oldz)*(z-oldz))> 5*GeoModelKernelUnits::cm) {
506 iLayer++;
507 bDescriptor.push_back(new InDetDD::TRT_BarrelDescriptor());
508 m_detectorManager->setBarrelDescriptor(bDescriptor.back());
509 bDescriptor.back()->setStrawTransformField(m_detectorManager->barrelTransformField(iABC),c);
510
511 //TK: Next, we are providing information about the Z
512 //dimensions of the active gas, to be used for reconstruction
513 //purposes. Personally I find "strawZDead" to be a slightly
514 //confusing choice of name for that method.
515
516 if((iABC==0)&&(iLayer<=m_data->barrelNumberOfLayersWithLargeDeadRegion )) {
517 //TK: these things should come back from makestraw...
518 double lengthOfActiveGas=
519 (m_data->barrelLengthOfStraw-m_data->barrelLengthOfTwister)/2.0 - m_data->lengthOfDeadRegion-m_data->barrelLengthOfLargeDeadRegion;
520 double startZOfActiveGas=activeGasZPositionStrawsWithLargeDeadRegion-lengthOfActiveGas/2.0;
521 bDescriptor.back()->strawZPos(activeGasZPositionStrawsWithLargeDeadRegion);
522 bDescriptor.back()->strawZDead(startZOfActiveGas);
523 bDescriptor.back()->strawLength(lengthOfActiveGas);
524 } else {
525 double lengthOfActiveGas=(m_data->barrelLengthOfStraw-m_data->barrelLengthOfTwister)/2.0 - 2*m_data->lengthOfDeadRegion;
526 double startZOfActiveGas=activeGasZPositionNormalStraws-lengthOfActiveGas/2.0;
527 bDescriptor.back()->strawZPos(activeGasZPositionNormalStraws);
528 bDescriptor.back()->strawZDead(startZOfActiveGas);
529 bDescriptor.back()->strawLength(lengthOfActiveGas);
530 }
531
532 }
533 bDescriptor.back()->addStraw(z,x);
534 oldx=x; oldz=z;
535 c++;
536
537 }
538
539 // Get a list of fibre radiators in the barrel;
540 std::set<const GeoVPhysVol *> barrelFibreRadiators;
541 std::set<const GeoVPhysVol *> strawPlanes;
542
543 // Now create m_data->nBarrelModulesUsed unique modules within each layer.
544 for (size_t iMod = 0; iMod<m_data->nBarrelModulesUsed;iMod++) {
545 GeoFullPhysVol * pShell = mapFPV["TRTShell-"+std::to_string(iABC)+"-"+std::to_string(iMod)];
546 GeoAlignableTransform * xfx1 = mapAX["TRTShell-"+std::to_string(iABC)+"-"+std::to_string(iMod)];
547
548
549
550 GeoVolumeCursor cursor(pShell);
551 while (!cursor.atEnd()) {
552 if (cursor.getVolume()->getLogVol()->getName().find("FibreRadiator") != std::string::npos) {
553 barrelFibreRadiators.insert(cursor.getVolume().get());
554 }
555 cursor.next();
556 }
557
558
559
560 // Register the alignable transfrom to the manager
561 // +ve and -ve are part of the same barrel. We use barrel_ec = -1.
562 Identifier idModule = idHelper->module_id(-1, iMod, iABC);
563 // In barrel frame (generally the same as the global frame)
564 m_detectorManager->addAlignableTransform(AlignmentLevelModule, idModule, xfx1, pShell, pBarrelVol);
565
566 Identifier TRT_Identifier = idHelper->straw_id(1, iMod, iABC, 1, 1);
567 int strawStatusHT = TRTCond::StrawStatus::Good;
568 if (m_statusAccessor) strawStatusHT = m_statusAccessor->status(TRT_Identifier);
569 refreshGasBarrel(strawStatusHT,pShell);
570
571 //-------------------------------------------------------------------//
572 // //
573 // Barrel readout: //
574 // //
575 //-------------------------------------------------------------------//
576
577 unsigned int nStrawLayers = m_detectorManager->getNumerology()->getNBarrelLayers(iABC);
578 for (unsigned int iStrawLayer=0;iStrawLayer<nStrawLayers; iStrawLayer++) { // limit stored as float!
579
580 unsigned int jStrawLayer=iStrawLayer;
581 if (iABC>0) jStrawLayer += m_detectorManager->getNumerology()->getNBarrelLayers(0);
582 if (iABC>1) jStrawLayer += m_detectorManager->getNumerology()->getNBarrelLayers(1);
583 //TK: just go from jStrawLayer=layerstart;jStrawLayer<layerend ?
584
585 InDetDD::TRT_BarrelDescriptor *bD=bDescriptor[jStrawLayer];
586
587 InDetDD::TRT_BarrelElement *element0 = new InDetDD::TRT_BarrelElement(pShell, bD, 0 , iABC, iMod, iStrawLayer, idHelper, m_detectorManager->conditions());
588 InDetDD::TRT_BarrelElement *element1 = new InDetDD::TRT_BarrelElement(pShell, bD, 1 , iABC, iMod, iStrawLayer, idHelper, m_detectorManager->conditions());
589
590 m_detectorManager->manageBarrelElement(element0);
591 m_detectorManager->manageBarrelElement(element1);
592 }
593
594 }//End "for (size_t iMod = ..." loop.
595
596 }
597
598 // Set up the nearest neighbor pointers: in R.
599 for (unsigned int e=0;e<2;e++) {
600 for (unsigned int iMod=0;iMod<m_data->nBarrelModulesUsed; iMod++) {
601 InDetDD::TRT_BarrelElement *prev=nullptr;
602 for (unsigned int iABC=0;iABC<m_data->nBarrelRings;iABC++) {
603 for (unsigned int s=0;s<m_detectorManager->getNumerology()->getNBarrelLayers(iABC); s++) {
604 InDetDD::TRT_BarrelElement *current = m_detectorManager->getBarrelElement(e,iABC, iMod, s);
605 if (prev && current) {
606 prev->setNextInR(current);
607 current->setPreviousInR(prev);
608 }
609 prev=current;
610 }
611 }
612 }
613 }
614
615 // Set up the nearest neighbor pointers: in Phi.
616 for (unsigned int e=0;e<2;e++) {
617 for (unsigned int iABC=0;iABC<m_data->nBarrelRings;iABC++) {
618 for (unsigned int s=0;s<m_detectorManager->getNumerology()->getNBarrelLayers(iABC); s++) {
619 InDetDD::TRT_BarrelElement *prev=nullptr;
620 for (unsigned int iMod=0;iMod<m_data->nBarrelModulesUsed; iMod++) {
621 InDetDD::TRT_BarrelElement *current = m_detectorManager->getBarrelElement(e,iABC, iMod, s);
622 if (prev && current) {
623 prev->setNextInPhi(current);
624 current->setPreviousInPhi(prev);
625 }
626 prev=current;
627 }
628 if (m_data->nBarrelModulesUsed==m_data->nBarrelModules) { // Full complement; then, we wrap!:
629 InDetDD::TRT_BarrelElement *first=m_detectorManager->getBarrelElement(e,iABC,0,s);
630 InDetDD::TRT_BarrelElement *last =m_detectorManager->getBarrelElement(e,iABC,m_data->nBarrelModules-1,s);
631 if (first && last) {
632 first->setPreviousInPhi(last);
633 last->setNextInPhi(first);
634 }
635 }
636 }
637 }
638 }
639 }//end of if (pBarrelVol)
640
641
642
643 //-----------------------------------------------------------------------//
644 // //
645 // Endcap Modules //
646 // //
647 //-----------------------------------------------------------------------//
648
649 // TK: This part could really use some cleanup and reordering.
650 // There is no need to repeat the same code for A, B & C endcaps.
651
652
653 // if none of the endcaps is being built we can return.
654 if (!(pEndCapABPlus || pEndCapABMinus || pEndCapCPlus || pEndCapCMinus)){
655 return;
656 }
657 unsigned int firstIndexOfA = 0;
658 unsigned int firstIndexOfB = m_data->endcapNumberOfAWheels;
659 unsigned int firstIndexOfC = m_data->endcapNumberOfAWheels + m_data->endcapNumberOfBWheels;
660
661 unsigned int indexUpperBound = firstIndexOfA + m_detectorManager->getNumerology()->getNEndcapWheels();
662
663 if (m_data->initialLayout) indexUpperBound = firstIndexOfC; // No wheel C.
664
665 const unsigned int nSides = 2;
666 const unsigned int nStrawLayMaxEc = 8;//hardcoded...
667
668 unsigned int iiSide, iiWheel, iiPlane, iiPhi, counter; //set of counters
669 GeoFullPhysVol *childPlane = nullptr;
670
671
672 double RotationsOfStrawPlanes[nStrawLayMaxEc]; //8 is hardcoded
673 double shiftForEachRotation = m_data->endCapShiftForEachRotation; // in units of deltaPhi
674 RotationsOfStrawPlanes[0] = 0.;
675
676 bool oldGeometry = true;
677 // Temporary way to determine old from new
678 if (shiftForEachRotation < 0) oldGeometry = false;
679
680 if (oldGeometry) {
681 // For old geometry
682 for (counter = 1; counter < nStrawLayMaxEc; counter++)
683 {
684 RotationsOfStrawPlanes[counter] = RotationsOfStrawPlanes[counter-1] + shiftForEachRotation;
685 if (RotationsOfStrawPlanes[counter] >= 1.)
686 RotationsOfStrawPlanes[counter] -= 1.;
687 }
688 } else {
689 // New geometry
690 double RotationsOfStrawPlanesTmp[nStrawLayMaxEc] = {0,0,0,0,2,2,2,2};
691 for (counter = 0; counter < nStrawLayMaxEc; counter++)
692 {
693 RotationsOfStrawPlanes[counter] = (counter * shiftForEachRotation) + RotationsOfStrawPlanesTmp[counter];
694 }
695 }
696
697 // Create and initialize by 0 arrays of descriptors
698 std::vector<InDetDD::TRT_EndcapDescriptor*> descriptorsAB[nSides][nStrawLayMaxEc];
699 std::vector<InDetDD::TRT_EndcapDescriptor*> descriptorsC[nSides][nStrawLayMaxEc];
700 InDetDD::TRT_EndcapDescriptor* pDescriptor = nullptr;
701 InDetDD::TRT_EndcapElement* element = nullptr;
702
703 for(iiSide = 0; iiSide<nSides; iiSide++) {
704 for(iiPlane = 0; iiPlane < nStrawLayMaxEc; iiPlane++) {
705 descriptorsAB[iiSide][iiPlane].resize (m_data->nEndcapPhi);
706 descriptorsC[iiSide][iiPlane].resize (m_data->nEndcapPhi);
707 }
708 }
709
710
711
712 // Do Wheels A and B if one of them is present
713 if (pEndCapABPlus || pEndCapABMinus) {
714 // -------------- Wheel A -----------------------
715
716
717 // Straw plane
718 setEndcapTransformField(firstIndexOfA);
719
720
721 // This is the straw pitch.
722 double deltaPhiForStrawsA = 360.*GeoModelKernelUnits::deg/m_data->endcapNumberOfStrawsInStrawLayer_AWheels;
723
724
725 // In reality the positive and negative endcaps are built identical, both in
726 // geometry and readout. The offline numbering however keeps phi numbering going
727 // in the same direction as global phi (righthanded direction).
728
729 // For the latest version we build +ve and negative endcaps identical.
730 // We also build the descriptors identical apart from the setting of startphi.
731 //
732 // The mapping is fixed (this must be reproduced in the sensitive
733 // detector and readout geometry) The mapping is 1-1 for the
734 // +ve endcap, for the -ve endcap it is as follows:
735 //
736 // ***************************************************************
737 // * Negative endcap (Endcap C) mapping. *
738 // * *
739 // * nSectors = 32 *
740 // * nStraws = num straws in sector *
741 // * sector -> (nSectors + nSectors/2 - sector - 1) % nSectors *
742 // * straw -> nStraws - 1 - straw *
743 // ***************************************************************
744 //
745 // For compatibility with old (wrong geometry) we rotate the strawlayers
746 // differently for the negative endcap than we do for the positive endcap.
747 // This is to allow the sensitive detector and readout geometry to have
748 // the same code for both layouts.
749 //
750 // Below we refere to online as the physical readout and offline as the offline
751 // identifier convetions.
752 // iiPhi corresponds to the "online" readout phi sector. This goes
753 // right handed in positive endcap and left handed in negative, where handedness
754 // is wrt to global frame.
755 // iiPhiOffline is the offline numbering which is always right handed.
756
757 for(iiSide=0; iiSide<nSides; iiSide++) {
758 // Wheel A
759 if (pCommonEndcapAB[iiSide]) {
760
761 for(iiWheel=firstIndexOfA; iiWheel < firstIndexOfB; iiWheel++)
762 {
763 //prepair to place wheel
764
765 GeoFullPhysVol* pWheelA = mapFPV["TRTWheelA-"
766 +std::to_string(iiSide)+"-"
767 +std::to_string(iiWheel)];
768
769 GeoAlignableTransform * xfAlignableModule = nullptr;
770
771 // Place planes in the wheel
772 for (iiPlane = 0; iiPlane < m_data->endCapNumberOfStrawLayersPerWheelA; iiPlane++)
773 {
774 // WheelA is subdivided into 4 alignable objects. (Every 4th straw layer)
775 // We create an alignable transform for each alignable module
776 // and multiply this by the transform for every straw layer in the "alignable module"
777 // The tranform is by default Identity.
778 if (iiPlane % 4 == 0) {
779 // Register alignable node
780 int barrel_ec = (iiSide) ? -2 : +2;
781 xfAlignableModule = mapAX["TRTWheelA-StrawPlane-"
782 +std::to_string(iiSide)+"-"
783 +std::to_string(iiWheel)+"-"
784 +std::to_string(iiPlane)];
785
786 Identifier idSubModule = idHelper->layer_id(barrel_ec, 0, iiWheel, iiPlane);
787 // We pass the parent volume as the local delta for this correction is the same as a local delta
788 // on the transformation of the wheel.
789 m_detectorManager->addAlignableTransform(AlignmentLevelSubWheel, idSubModule, xfAlignableModule, pWheelA);
790 }
791
792 // phiPlane is phi of straw 0, sector 0 (online numbering)
793 double phiPlane = m_data->endCapPhiOfFirstStraw + RotationsOfStrawPlanes[iiPlane%nStrawLayMaxEc]*deltaPhiForStrawsA;
794
795 // For compatibility with old geometry we have to shift every eighth wheel by 1 straw pitch.
796 if(iiSide && oldGeometry && (iiPlane%8 == 0)) {
797 phiPlane += deltaPhiForStrawsA;
798 }
799
800 Identifier TRT_Identifier;
801 int bar_ec = (iiSide) ? -2 : +2;
802 TRT_Identifier = idHelper->straw_id(bar_ec, 1, iiWheel, 1, 1);
803 int strawStatusHT = TRTCond::StrawStatus::Good;
804 if (m_statusAccessor) strawStatusHT = m_statusAccessor->status(TRT_Identifier);
805
806
807 childPlane = mapFPV["TRTWheelA-StrawPlane-"
808 +std::to_string(iiSide)+"-"
809 +std::to_string(iiWheel)+"-"
810 +std::to_string(iiPlane)];
811
812 refreshGasEndcap(strawStatusHT,childPlane);
813
814 // Create descriptors
815 // Just do it for the first wheel
816 if(iiWheel==firstIndexOfA && iiPlane < nStrawLayMaxEc)
817 for(iiPhi = 0; iiPhi < m_data->nEndcapPhi; iiPhi++)
818 {
819
820 pDescriptor = new InDetDD::TRT_EndcapDescriptor();
821 m_detectorManager->setEndcapDescriptor(pDescriptor);
822
823 pDescriptor->nStraws() = m_data->endcapNumberOfStrawsInStrawLayer_AWheels/m_data->nEndcapPhi;
824 pDescriptor->strawPitch() = deltaPhiForStrawsA;
825
826 double startPhi = phiPlane + iiPhi * pDescriptor->strawPitch() * pDescriptor->nStraws();
827
828 // For negative endcap the startPhi is the last straw in the physical sector
829 // phi -> phi + strawPitch*(n-1)
830 // it then gets rotated 180 around y axis
831 // phi -> pi - phi
832 if (iiSide) {
833 startPhi = GeoModelKernelUnits::pi - (startPhi + pDescriptor->strawPitch() * (pDescriptor->nStraws() - 1));
834 }
835
836 // Make sure its between -pi and pi.
837 if (startPhi <= -GeoModelKernelUnits::pi) startPhi += 2*GeoModelKernelUnits::pi;
838 if (startPhi > GeoModelKernelUnits::pi) startPhi -= 2*GeoModelKernelUnits::pi;
839
840 pDescriptor->startPhi() = startPhi;
841
842 pDescriptor->strawLength() = m_data->endCapOuterRadiusOfSupportA - m_data->endCapRadialThicknessOfOuterSupportA
843 - 2*m_data->lengthOfDeadRegion - m_data->endCapRadialThicknessOfInnerSupportA - m_data->endCapInnerRadiusOfSupportA;
844 pDescriptor->innerRadius() = m_data->endCapInnerRadiusOfSupportA + m_data->endCapRadialThicknessOfInnerSupportA
845 + m_data->lengthOfDeadRegion;
846 pDescriptor->setStrawTransformField(m_detectorManager->endcapTransformField(0),iiPhi*pDescriptor->nStraws());
847
848 descriptorsAB[iiSide][iiPlane%nStrawLayMaxEc][iiPhi] = pDescriptor;
849 }
850 // Create elements
851 for(iiPhi = 0; iiPhi < m_data->nEndcapPhi; iiPhi++)
852 {
853 // m_data->nEndcapPhi assumed to be even.
854 // For positive endcap online == offline. For negative endcap we rotate 180 deg about y axis so
855 // sector 0 -> 15, 15 -> 0, 16 -> 31, 31 -> 16, etc. This is achieved with
856 // sector -> (nSectors + nSectors/2 - sector - 1) % nSectors
857 int iiPhiOffline = (iiSide==0) ? iiPhi : (3*m_data->nEndcapPhi/2 - iiPhi - 1)% m_data->nEndcapPhi;
858 element = new InDetDD::TRT_EndcapElement(childPlane,
859 descriptorsAB[iiSide][iiPlane%nStrawLayMaxEc][iiPhi],
860 iiSide==0,
861 iiWheel,
862 iiPlane,
863 iiPhiOffline,
864 idHelper,
865 m_detectorManager->conditions());
866 m_detectorManager->manageEndcapElement(element);
867 }
868 }
869 // Place Inner/Outer supports in the wheel
870
871 // Place wheel in the Endcap Volume
872 GeoAlignableTransform * xfWheel = mapAX["TRTWheelA-"
873 +std::to_string(iiSide)+"-"
874 +std::to_string(iiWheel)];
875
876 // Register alignable node
877 int barrel_ec = (iiSide) ? -2 : +2;
878 Identifier idModule = idHelper->module_id(barrel_ec, 0, iiWheel);
879 m_detectorManager->addAlignableTransform(AlignmentLevelModule, idModule, xfWheel, pWheelA);
880
881 } // iiWheel loop for Wheel A
882 } // if (pCommonEndcapAB[iiSide]) block for Wheel A
883 } // iiSide loop for Wheel A
884
885
886
887 // --------------- Wheel B ----------------------------
888
889 // Straw plane
890 setEndcapTransformField(firstIndexOfB);
891
892 for(iiSide=0; iiSide<nSides; iiSide++) {
893
894 // Wheel B
895 if (pCommonEndcapAB[iiSide]) {
896 for(iiWheel=firstIndexOfB; iiWheel < firstIndexOfC; iiWheel++)
897 {
898
899 GeoFullPhysVol* pWheelB = mapFPV["TRTWheelB-"
900 +std::to_string(iiSide)+"-"
901 +std::to_string(iiWheel)];
902
903 GeoAlignableTransform * xfAlignableModule = nullptr;
904
905 // Place planes in the wheel
906 for (iiPlane = 0; iiPlane < m_data->endCapNumberOfStrawLayersPerWheelB; iiPlane++)
907 {
908
909 // Each wheel in WheelB is subdivided into 2 alignable objects (every 4th straw layer)
910 // We create an alignable transform for each alignable module
911 // and multiply this by the transform for every straw layer in the "alignable module"
912 // The tranform is by default Identity.
913 if (iiPlane % 4 == 0) {
914 // Register alignable node
915 int barrel_ec = (iiSide) ? -2 : +2;
916 xfAlignableModule = mapAX["TRTWheelB-StrawPlane-"
917 +std::to_string(iiSide)+"-"
918 +std::to_string(iiWheel)+"-"
919 +std::to_string(iiPlane)];
920
921
922
923 Identifier idSubModule = idHelper->layer_id(barrel_ec, 0, iiWheel, iiPlane);
924 // We pass the parent volume as the local delta for this correction is the same as a local delta
925 // on the transformation of the wheel.
926 m_detectorManager->addAlignableTransform(AlignmentLevelSubWheel, idSubModule, xfAlignableModule, pWheelB);
927 }
928
929 Identifier TRT_Identifier;
930 int bar_ec = (iiSide) ? -2 : +2;
931 TRT_Identifier = idHelper->straw_id(bar_ec, 1, iiWheel, 1, 1);
932 int strawStatusHT = TRTCond::StrawStatus::Good;
933 if (m_statusAccessor) strawStatusHT = m_statusAccessor->status(TRT_Identifier);
934
935 childPlane = mapFPV["TRTWheelB-StrawPlane-"
936 +std::to_string(iiSide)+"-"
937 +std::to_string(iiWheel)+"-"
938 +std::to_string(iiPlane)];
939 refreshGasEndcap(strawStatusHT,childPlane);
940
941
942
943 // Create elements
944 for(iiPhi = 0; iiPhi < m_data->nEndcapPhi; iiPhi++)
945 {
946 // m_data->nEndcapPhi assumed to be even.
947 // For positive endcap online == offline. For negative endcap we rotate 180 deg about y axis so
948 // sector 0 -> 15, 15 -> 0, 16 -> 31, 31 -> 16, etc. This is achieved with
949 // sector -> (nSectors + nSectors/2 - sector - 1) % nSectors
950 int iiPhiOffline = (iiSide==0) ? iiPhi : (3*m_data->nEndcapPhi/2 - iiPhi - 1)% m_data->nEndcapPhi;
951 element = new InDetDD::TRT_EndcapElement(childPlane,
952 descriptorsAB[iiSide][iiPlane%nStrawLayMaxEc][iiPhi],
953 iiSide==0,
954 iiWheel,
955 iiPlane,
956 iiPhiOffline,
957 idHelper,
958 m_detectorManager->conditions());
959 m_detectorManager->manageEndcapElement(element);
960 }
961 }
962
963 // Place wheel in the Endcap Volume
964 GeoAlignableTransform * xfWheel = mapAX["TRTWheelB-"
965 +std::to_string(iiSide)+"-"
966 +std::to_string(iiWheel)];
967 // Register alignable node
968 int barrel_ec = (iiSide) ? -2 : +2;
969 Identifier idModule = idHelper->module_id(barrel_ec, 0, iiWheel);
970 m_detectorManager->addAlignableTransform(AlignmentLevelModule, idModule, xfWheel, pWheelB);
971 }// iiWheel loop for Wheel B
972 } // if (pCommonEndcapAB[iiSide]) block for Wheel B
973 } // iiSide loop for Wheel B
974
975 } // end AB
976
977 // ---------------- Wheel C ---------------------------
978 // Not present in initial layout
979 if (pEndCapCPlus || pEndCapCMinus) {
980
981 setEndcapTransformField(firstIndexOfC);
982
983 // This is the straw pitch.
984 double deltaPhiForStrawsC = 360.*GeoModelKernelUnits::deg/m_data->endcapNumberOfStrawsInStrawLayer_CWheels;
985
986 for(iiSide=0; iiSide<nSides; iiSide++) {
987 // Wheel C
988 if (pCommonEndcapC[iiSide]) {
989 for(iiWheel=firstIndexOfC; iiWheel < indexUpperBound; iiWheel++)
990 {
991 GeoFullPhysVol* pWheelC = mapFPV["TRTWheelC-"
992 +std::to_string(iiSide)+"-"
993 +std::to_string(iiWheel)];
994
995
996
997 // Place planes in the wheel
998 for (iiPlane = 0; iiPlane < m_data->endCapNumberOfStrawLayersPerWheelC; iiPlane++)
999 {
1000 // phiPlane is phi of straw 0, sector 0 (online numbering)
1001 double phiPlane = m_data->endCapPhiOfFirstStraw + RotationsOfStrawPlanes[iiPlane%nStrawLayMaxEc]*deltaPhiForStrawsC;
1002
1003 // For compatibility with old geometry we have to shift every eighth wheel by 1 straw pitch.
1004 if(iiSide && oldGeometry && (iiPlane%8 == 0)) {
1005 phiPlane += deltaPhiForStrawsC;
1006 }
1007
1008
1009
1010 childPlane = mapFPV["TRTWheelC-StrawPlane-"
1011 +std::to_string(iiSide)+"-"
1012 +std::to_string(iiWheel)+"-"
1013 +std::to_string(iiPlane)];
1014
1015
1016 // Create descriptors
1017 // Just do it for the first wheel
1018 if(iiWheel==firstIndexOfC && iiPlane < nStrawLayMaxEc)
1019 for(iiPhi = 0; iiPhi < m_data->nEndcapPhi; iiPhi++)
1020 {
1021 pDescriptor = new InDetDD::TRT_EndcapDescriptor();
1022 m_detectorManager->setEndcapDescriptor(pDescriptor);
1023
1024 pDescriptor->nStraws() = m_data->endcapNumberOfStrawsInStrawLayer_CWheels/m_data->nEndcapPhi;
1025 pDescriptor->strawPitch() = deltaPhiForStrawsC;
1026
1027
1028 double startPhi = phiPlane + iiPhi * pDescriptor->strawPitch() * pDescriptor->nStraws();
1029
1030 // For negative endcap the startPhi is the last straw in the physical sector, it then gets
1031 // rotated 180 around y axis (phi -> pi - phi)
1032 if (iiSide) {
1033 startPhi = GeoModelKernelUnits::pi - (startPhi + pDescriptor->strawPitch() * (pDescriptor->nStraws() - 1));
1034 }
1035
1036 // Make sure its between -pi and pi.
1037 if (startPhi <= -GeoModelKernelUnits::pi) startPhi += 2*GeoModelKernelUnits::pi;
1038 if (startPhi > GeoModelKernelUnits::pi) startPhi -= 2*GeoModelKernelUnits::pi;
1039
1040
1041 pDescriptor->startPhi() = startPhi;
1042
1043 pDescriptor->strawLength() = m_data->endCapOuterRadiusOfSupportC - m_data->endCapRadialThicknessOfOuterSupportC
1044 - 2*m_data->lengthOfDeadRegion - m_data->endCapRadialThicknessOfInnerSupportC - m_data->endCapInnerRadiusOfSupportC;
1045 pDescriptor->innerRadius() = m_data->endCapInnerRadiusOfSupportC + m_data->endCapRadialThicknessOfInnerSupportC + m_data->lengthOfDeadRegion;
1046 pDescriptor->setStrawTransformField(m_detectorManager->endcapTransformField(2),iiPhi*pDescriptor->nStraws());
1047
1048
1049 descriptorsC[iiSide][iiPlane%nStrawLayMaxEc][iiPhi] = pDescriptor;
1050 }
1051
1052 // Create elements
1053 for(iiPhi = 0; iiPhi < m_data->nEndcapPhi; iiPhi++)
1054 {
1055 // m_data->nEndcapPhi assumed to be even.
1056 // For positive endcap online == offline. For negative endcap we rotate 180 deg about y axis so
1057 // sector 0 -> 15, 15 -> 0, 16 -> 31, 31 -> 16, etc. This is achieved with
1058 // sector -> (nSectors + nSectors/2 - sector - 1) % nSectors
1059 int iiPhiOffline = (iiSide==0) ? iiPhi : (3*m_data->nEndcapPhi/2 - iiPhi - 1)% m_data->nEndcapPhi;
1060 element = new InDetDD::TRT_EndcapElement(childPlane,
1061 descriptorsC[iiSide][iiPlane%nStrawLayMaxEc][iiPhi],
1062 iiSide==0,
1063 iiWheel,
1064 iiPlane,
1065 iiPhiOffline,
1066 idHelper,
1067 m_detectorManager->conditions());
1068 m_detectorManager->manageEndcapElement(element);
1069 }
1070 }
1071
1072
1073 // Place wheel in the Endcap Volume
1074 GeoAlignableTransform * xfWheel = mapAX["TRTWheelC-"
1075 +std::to_string(iiSide)+"-"
1076 +std::to_string(iiWheel)];
1077
1078 // Register alignable node
1079 int barrel_ec = (iiSide) ? -2 : +2;
1080 Identifier idModule = idHelper->module_id(barrel_ec, 0, iiWheel);
1081 m_detectorManager->addAlignableTransform(AlignmentLevelModule, idModule, xfWheel, pWheelC);
1082
1083
1084 } // iiWheel loop for Wheel C
1085 } // if (pCommonEndcapC[iiSide]) block for Wheel C
1086 } // iiSide loop for Wheel C
1087
1088 } // End Wheel C
1089
1090
1091 // Set up the nearest neighbor pointers: in Z
1092 for (iiSide=0; iiSide<2; iiSide++)
1093 for(iiPhi=0; iiPhi<m_data->nEndcapPhi; iiPhi++)
1094 {
1095 InDetDD::TRT_EndcapElement *prev = nullptr;
1096 for (iiWheel=0; iiWheel<indexUpperBound; iiWheel++)
1097 for (iiPlane=0; iiPlane<m_detectorManager->getNumerology()->getNEndcapLayers(iiWheel); iiPlane++)
1098 {
1099 InDetDD::TRT_EndcapElement *current = m_detectorManager->getEndcapElement(iiSide, iiWheel, iiPlane, iiPhi);
1100 if (prev && current)
1101 {
1102 prev->setNextInZ(current);
1103 current->setPreviousInZ(prev);
1104 }
1105 prev=current;
1106 }
1107 }
1108}
1109
1111
1112
1113
1114
1115//GeoPhysVol * TRTDetectorFactory_Lite::makeStraw( double& activeGasZPosition, bool hasLargeDeadRegion /*= false*/ ) const {
1116double TRTDetectorFactory_Lite::activeGasZPosition(bool hasLargeDeadRegion /*= false*/) const {
1117
1118 double lengthOfInnerDeadRegion= hasLargeDeadRegion ? m_data->barrelLengthOfLargeDeadRegion : m_data->lengthOfDeadRegion ;
1119 double lengthOfActiveGas = (m_data->barrelLengthOfStraw-m_data->barrelLengthOfTwister)/2.0 - m_data->lengthOfDeadRegion - lengthOfInnerDeadRegion;
1120 return (lengthOfActiveGas + m_data->barrelLengthOfTwister) / 2. + lengthOfInnerDeadRegion; // middle of lengthOfActiveGas
1121
1122}
1123
1124
1125
1126
1128//
1130
1131 size_t nstraws=0;
1132
1133 //A and B wheels have similar straw planes, but the C wheels are different.
1134 // const size_t firstIndexOfC = 15; //hardcoded
1135 const size_t firstIndexOfC = 14; //hardcoded
1136
1137 double R0, R1;
1138 if (w >= firstIndexOfC) {
1139 //C wheels:
1140 nstraws=m_data->endcapNumberOfStrawsInStrawLayer_CWheels;
1141 R0 = m_data->endcapOuterRadiusOfInnerSupport_wheelC;
1142 R1 = m_data->endcapInnerRadiusOfOuterSupport_wheelC;
1143 } else {
1144 //A and B wheels:
1145 R0 = m_data->endcapOuterRadiusOfInnerSupport_wheelAB;
1146 R1 = m_data->endcapInnerRadiusOfOuterSupport_wheelAB;
1147 nstraws=m_data->endcapNumberOfStrawsInStrawLayer_AWheels;
1148 }
1149
1150 double pos = 0.5*(R0+R1);
1151
1152 // Positioning of straws :
1153 double dphi = 2*M_PI/ nstraws;
1154 GeoTrf::RotateZ3D Rz(1.0);// Radians!
1155 GeoTrf::TranslateX3D Tx(1.0);// MM! TK: actually this doesnt need to be interpreted as mm? Just as a dimensionless 1. (i guess)
1156 GeoTrf::TranslateY3D Ty(1.0);// MM!
1157 Variable i;
1158 Sin sin;
1159 Cos cos;
1160 TRANSFUNCTION tx = Pow(Tx,pos*cos(dphi*i))*Pow(Ty,pos*sin(dphi*i))*Pow(Rz,dphi*i)*GeoTrf::RotateY3D(-90*GeoModelKernelUnits::deg);
1161
1162 // Give this parameterization also to the readout geometry:
1163 if (w<firstIndexOfC) {
1164 m_detectorManager->setEndcapTransformField(0,tx.clone());
1165 m_detectorManager->setEndcapTransformField(1,tx.clone());
1166 }
1167 else {
1168 m_detectorManager->setEndcapTransformField(2,tx.clone());
1169 }
1170 return;
1171
1172}
1173
1174
1175// These methods update the gas.
1176void TRTDetectorFactory_Lite::refreshGasEndcap(int strawStatusHT, GeoVPhysVol *strawPlane) {
1177
1178 const GeoMaterial *material = m_xenonGas.get();
1179
1180 if (m_statusAccessor && (strawStatusHT == TRTCond::StrawStatus::Dead ||
1181 strawStatusHT == TRTCond::StrawStatus::Argon))
1182 material= m_argonGas.get();
1183
1184 // The volume hierarchy from here is: strawPlane>>straw>>gas
1185 GeoVolumeCursor cursor0(strawPlane);
1186 if (!cursor0.atEnd()) {
1187 const GeoVPhysVol *v1=cursor0.getVolume().get();
1188 GeoVolumeCursor cursor1(v1);
1189 if (!cursor1.atEnd()) {
1190 ATH_MSG_DEBUG("ENDCAP: REFRESHING GAS MIXTURE " << strawPlane->getLogVol()->getName() << " -->" << material->getName());
1191 cursor1.getVolume()->getLogVol()->setMaterial(material);
1192 }
1193 }
1194}
1195
1196void TRTDetectorFactory_Lite::refreshGasBarrel(int strawStatusHT, GeoVPhysVol *shell) {
1197
1198 const GeoMaterial *material = m_xenonGas.get();
1199
1200 if (m_statusAccessor && (strawStatusHT == TRTCond::StrawStatus::Dead ||
1201 strawStatusHT == TRTCond::StrawStatus::Argon))
1202 material= m_argonGas.get();
1203
1204 GeoVolumeCursor cursor0(shell);
1205 if (!cursor0.atEnd()) {
1206 const GeoVPhysVol *v1=cursor0.getVolume().get();
1207 GeoCountVolAndSTAction counter;
1208 v1->exec(&counter);
1209 for (unsigned int i=0;i<counter.getCount();i++) {
1210 GeoAccessVolAndSTAction accessor(i);
1211 v1->exec(&accessor);
1212 const GeoSerialTransformer *st=accessor.getSerialTransformer();
1213 if (st) {
1214 const GeoVPhysVol *v2=st->getVolume().get();
1215 GeoVolumeCursor cursor1(v2);
1216 if (!cursor1.atEnd()) {
1217 const GeoVPhysVol *v3=cursor1.getVolume();
1218 GeoVolumeCursor cursor2(v3);
1219 while (!cursor2.atEnd()) {
1220 std::string regionName=cursor2.getVolume()->getLogVol()->getName();
1221 if (regionName=="GasMA" || regionName=="DeadRegion" || regionName=="InnerDeadRegion") {
1222 ATH_MSG_DEBUG("BARREL: REFRESHING GAS MIXTURE " << cursor2.getVolume()->getLogVol()->getName() << " -->" << material->getName());
1223 cursor2.getVolume()->getLogVol()->setMaterial(material);
1224 }
1225 cursor2.next();
1226 }
1227 }
1228 }
1229 }
1230 }
1231
1232}
1233
#define M_PI
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_DEBUG(x)
Definition of the abstract IRDBAccessSvc interface.
std::shared_ptr< IRDBRecordset > IRDBRecordset_ptr
Definition of the abstract IRDBRecord interface.
Definition of the abstract IRDBRecordset interface.
This is an Identifier helper class for the TRT subdetector.
#define y
#define x
#define z
IRDBAccessSvc is an abstract interface to the athena service that provides the following functionalit...
virtual IRDBRecordset_ptr getRecordsetPtr(const std::string &node, const std::string &tag, const std::string &tag2node="", const std::string &connName="ATLASDD")=0
Provides access to the Recordset object containing HVS-tagged data.
IRDBRecord is one record in the IRDBRecordset object.
Definition IRDBRecord.h:27
virtual double getDouble(const std::string &fieldName) const =0
Get double field value.
virtual unsigned int size() const =0
Class to hold various Athena components.
DetectorFactoryBase(InDetDD::AthenaComps *athenaComps)
InDetDD::AthenaComps * getAthenaComps()
Local Straw Positions (from the center of the module.)
Extended TRT_BaseElement to describe a TRT readout element, this is a planar layer with n ( order of ...
void setNextInPhi(const TRT_BarrelElement *element)
Sets the next-in-phi detector.
void setNextInR(const TRT_BarrelElement *element)
Sets the next-in-r detector.
The Detector Manager for all TRT Detector elements, it acts as the interface to the detector elements...
class TRT_EndcapDescriptor
double & strawPitch()
The straw pitch (angular!
void setStrawTransformField(const GeoXF::Function *xf, size_t offsetInto)
Sets the transform field for straws and offset.
double & startPhi()
The starting phi (angular!
unsigned int & nStraws()
The number of straws in a module:
double & innerRadius()
The inner radius:
Extended class of a TRT_BaseElement to describe a readout elment in the endcap.
void setNextInZ(const TRT_EndcapElement *element)
Set Next in Z.
Class to hold version information consisting of tag, name layout and description as strings,...
Definition Version.h:24
virtual void create(GeoPhysVol *world) override
virtual const InDetDD::TRT_DetectorManager * getDetectorManager() const override
void refreshGasEndcap(int strawStatusHT, GeoVPhysVol *strawPlane)
GeoIntrusivePtr< const GeoMaterial > m_argonGas
InDetDD::TRT_DetectorManager * m_detectorManager
std::unique_ptr< const TRTStrawStatusAccessor > m_statusAccessor
GeoIntrusivePtr< const GeoMaterial > m_xenonGas
std::unique_ptr< TRTParameterInterface > m_data
double activeGasZPosition(bool hasLargeDeadRegion=false) const
void refreshGasBarrel(int strawStatusHT, GeoVPhysVol *shell)
TRTDetectorFactory_Lite(GeoModelIO::ReadGeoModel *sqliteReader, InDetDD::AthenaComps *athenaComps, std::unique_ptr< const TRTStrawStatusAccessor > statusAccessor, bool useOldActiveGasMixture, bool DC2CompatibleBarrelCoordinates, bool alignable, bool useDynamicAlignmentFolders)
GeoModelIO::ReadGeoModel * m_sqliteReader
This is an Identifier helper class for the TRT subdetector.
Definition TRT_ID.h:82
Identifier layer_id(int barrel_ec, int phi_module, int layer_or_wheel, int straw_layer) const
For an individual straw layer.
Definition TRT_ID.h:494
Identifier straw_id(int barrel_ec, int phi_module, int layer_or_wheel, int straw_layer, int straw) const
Three ways of getting id for a single straw:
Definition TRT_ID.h:575
Identifier module_id(int barrel_ec, int phi_module, int layer_or_wheel) const
For an individual module phi sector.
Definition TRT_ID.h:442
Identifier barrel_ec_id(int barrel_ec) const
For +/-barrel or +/-endcap id.
Definition TRT_ID.h:411
Wrapper around a histogram which allows for some additional filling patterns and data manipulation.
int r
Definition globals.cxx:22
std::string description
glabal timer - how long have I taken so far?
Definition hcg.cxx:91
Message Stream Member.
@ timedependent_run2
STL namespace.