Project
Loading...
Searching...
No Matches
GeometryTGeo.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
13#include <TGeoManager.h>
15
17
18namespace o2
19{
20namespace trk
21{
22std::unique_ptr<o2::trk::GeometryTGeo> GeometryTGeo::sInstance;
23
24// Names
25std::string GeometryTGeo::sVolumeName = "TRKV";
26std::string GeometryTGeo::sLayerName = "TRKLayer";
27std::string GeometryTGeo::sPetalAssemblyName = "PETAL";
28std::string GeometryTGeo::sPetalName = "PETALCASE";
29std::string GeometryTGeo::sPetalDiskName = "DISK";
30std::string GeometryTGeo::sPetalLayerName = "LAYER";
31std::string GeometryTGeo::sStaveName = "TRKStave";
32std::string GeometryTGeo::sChipName = "TRKChip";
33std::string GeometryTGeo::sSensorName = "TRKSensor";
34
35std::string GeometryTGeo::sWrapperVolumeName = "TRKUWrapVol";
36
38{
39 if (!mOwner) {
40 mOwner = true;
41 sInstance.release();
42 }
43}
44GeometryTGeo::GeometryTGeo(bool build, int loadTrans) : DetMatrixCache(detectors::DetID::TRK)
45{
46 if (sInstance) {
47 LOGP(fatal, "Invalid use of public constructor: o2::trk::GeometryTGeo instance exists");
48 }
49 mLayerToWrapper.fill(-1);
50 if (build) {
51 Build(loadTrans);
52 }
53}
54
55//__________________________________________________________________________
56void GeometryTGeo::Build(int loadTrans)
57{
62
63 if (isBuilt()) {
64 LOGP(warning, "Already built");
65 return; // already initialized
66 }
67
68 if (gGeoManager == nullptr) {
69 LOGP(fatal, "Geometry is not loaded");
70 }
71
77
87
88 for (int i = 0; i < mNumberOfLayersMLOT; i++) {
89 std::cout << "Layer MLOT: " << i << std::endl;
92 }
93
94 int numberOfChipsTotal = 0;
95
97 for (int i = 0; i < mNumberOfPetalsVD; i++) {
99 numberOfChipsTotal += mNumberOfChipsPerPetalVD[i];
100 mLastChipIndex[i] = numberOfChipsTotal - 1;
101 mLastChipIndexVD[i] = numberOfChipsTotal - 1;
102 }
103
105 for (int i = 0; i < mNumberOfLayersMLOT; i++) {
106 mNumberOfChipsPerLayerMLOT[i] = extractNumberOfStavesMLOT(i) * extractNumberOfHalfStavesMLOT(i); // for the moment, considering 1 half stave = 1 chip. TODO: add the final segmentation in chips
107 numberOfChipsTotal += mNumberOfChipsPerLayerMLOT[i];
108 mLastChipIndex[i + mNumberOfPetalsVD] = numberOfChipsTotal - 1;
109 mLastChipIndexMLOT[i] = numberOfChipsTotal - 1;
110 }
111
112 setSize(numberOfChipsTotal);
113 fillMatrixCache(loadTrans);
114}
115
116//__________________________________________________________________________
118{
119 if (index <= mLastChipIndexVD[mLastChipIndexVD.size() - 1]) {
120 return 0;
121 } else if (index > mLastChipIndexVD[mLastChipIndexVD.size() - 1]) {
122 return 1;
123 }
124 return -1;
125}
126
127//__________________________________________________________________________
129{
130 int petalcase = 0;
131
132 int subDetID = getSubDetID(index);
133 if (subDetID == 1) {
134 return -1;
135 }
136
137 else if (index <= mLastChipIndexVD[mNumberOfPetalsVD - 1]) {
138 while (index > mLastChipIndexVD[petalcase]) {
139 petalcase++;
140 }
141 }
142 return petalcase;
143}
144
145//__________________________________________________________________________
147{
148 int subDetID = getSubDetID(index);
149 int petalcase = getPetalCase(index);
150 int lay = 0;
151
152 if (subDetID == 0) {
154 return -1;
155 }
156 return index % mNumberOfChipsPerPetalVD[petalcase];
157 } else if (subDetID == 1) {
158 while (index > mLastChipIndex[lay]) {
159 lay++;
160 }
161 return lay - mNumberOfPetalsVD;
162 }
163 return -1;
164}
165//__________________________________________________________________________
167{
168 int subDetID = getSubDetID(index);
169 int lay = getLayer(index);
170 int petalcase = getPetalCase(index);
171
172 if (subDetID == 0) {
173 return -1;
174 } else if (subDetID == 1) {
175 int lay = getLayer(index);
176 index -= getFirstChipIndex(lay, petalcase, subDetID); // get the index of the sensing element in the layer
177 return index / mNumberOfHalfStaves[lay];
178 }
179 return -1;
180}
181
182//__________________________________________________________________________
184{
185 int subDetID = getSubDetID(index);
186 int lay = getLayer(index);
187 int petalcase = getPetalCase(index);
188 int stave = getStave(index);
189
190 if (subDetID == 0) {
191 return -1;
192 } else if (subDetID == 1) {
193 int lay = getLayer(index);
194 index -= getFirstChipIndex(lay, petalcase, subDetID); // get the index of the sensing element in the layer
195 return index % 2;
196 }
197 return -1;
198}
199
200//__________________________________________________________________________
202{
203 int subDetID = getSubDetID(index);
204 int petalcase = getPetalCase(index);
205
206 if (subDetID == 0) {
208 return -1;
209 }
210 return (index % mNumberOfChipsPerPetalVD[petalcase]) - mNumberOfLayersVD;
211 }
212
213 return -1;
214}
215
216//__________________________________________________________________________
217int GeometryTGeo::getChipIndex(int subDetID, int petalcase, int disk, int lay, int stave, int halfstave) const
218{
219 if (subDetID == 0) { // VD
220 if (lay == -1) { // disk
221 return getFirstChipIndex(lay, petalcase, subDetID) + mNumberOfLayersVD + disk;
222 } else { // layer
223 return getFirstChipIndex(lay, petalcase, subDetID) + lay;
224 }
225 } else if (subDetID == 1) { // MLOT
226 if (mNumberOfHalfStaves[lay] == 2) { // staggered geometry
227 return getFirstChipIndex(lay, petalcase, subDetID) + stave * mNumberOfHalfStaves[lay] + halfstave;
228 } else if (mNumberOfHalfStaves[lay] == 1) { // turbo geometry
229 return getFirstChipIndex(lay, petalcase, subDetID) + stave;
230 }
231 }
232 return -1; // not found
233}
234
235//__________________________________________________________________________
236int GeometryTGeo::getChipIndex(int subDetID, int volume, int lay, int stave, int halfstave) const
237{
238 if (subDetID == 0) { // VD
239 return volume;
240
241 } else if (subDetID == 1) { // MLOT
242 if (mNumberOfHalfStaves[lay] == 2) { // staggered geometry
243 return getFirstChipIndex(lay, -1, subDetID) + stave * mNumberOfHalfStaves[lay] + halfstave;
244 } else if (mNumberOfHalfStaves[lay] == 1) { // turbo geometry
245 return getFirstChipIndex(lay, -1, subDetID) + stave;
246 }
247 }
248 return -1; // not found
249}
250
251//__________________________________________________________________________
252bool GeometryTGeo::getChipID(int index, int& subDetID, int& petalcase, int& disk, int& lay, int& stave, int& halfstave) const
253{
254 subDetID = getSubDetID(index);
255 petalcase = getPetalCase(index);
256 disk = getDisk(index);
257 lay = getLayer(index);
258 stave = getStave(index);
259 halfstave = getHalfStave(index);
260
261 return kTRUE;
262}
263
264//__________________________________________________________________________
266{
267
268 int subDetID, petalcase, disk, layer, stave, halfstave;
269 getChipID(index, subDetID, petalcase, disk, layer, stave, halfstave);
270
271 // PrintChipID(index, subDetID, petalcase, disk, layer, stave, halfstave);
272
273 // TString path = "/cave_1/barrel_1/TRKV_2/TRKLayer0_1/TRKStave0_1/TRKChip0_1/TRKSensor0_1/"; /// dummy path, to be used for tests
274 TString path = Form("/cave_1/barrel_1/%s_2/", GeometryTGeo::getTRKVolPattern());
275
276 if (subDetID == 0) { // VD
277 if (disk >= 0) {
278 path += Form("%s%d_%s%d_1/", getTRKPetalPattern(), petalcase, getTRKPetalDiskPattern(), disk); // PETALCASEx_DISKy_1
279 path += Form("%s%d_%s%d_%s%d_1/", getTRKPetalPattern(), petalcase, getTRKPetalDiskPattern(), disk, getTRKChipPattern(), disk); // PETALCASEx_DISKy_TRKChipy_1
280 path += Form("%s%d_%s%d_%s%d_1/", getTRKPetalPattern(), petalcase, getTRKPetalDiskPattern(), disk, getTRKSensorPattern(), disk); // PETALCASEx_DISKy_TRKSensory_1
281 } else if (layer >= 0) {
282 path += Form("%s%d_%s%d_1/", getTRKPetalPattern(), petalcase, getTRKPetalLayerPattern(), layer); // PETALCASEx_LAYERy_1
283 path += Form("%s%d_%s%d_%s%d_1/", getTRKPetalPattern(), petalcase, getTRKPetalLayerPattern(), layer, getTRKStavePattern(), layer); // PETALCASEx_LAYERy_TRKStavey_1
284 path += Form("%s%d_%s%d_%s%d_1/", getTRKPetalPattern(), petalcase, getTRKPetalLayerPattern(), layer, getTRKChipPattern(), layer); // PETALCASEx_LAYERy_TRKChipy_1
285 path += Form("%s%d_%s%d_%s%d_1/", getTRKPetalPattern(), petalcase, getTRKPetalLayerPattern(), layer, getTRKSensorPattern(), layer); // PETALCASEx_LAYERy_TRKSensory_1
286 }
287 } else if (subDetID == 1) { // MLOT
288 path += Form("%s%d_1/", getTRKLayerPattern(), layer); // TRKLayerx_1
289 path += Form("%s%d_%d/", getTRKStavePattern(), layer, stave); // TRKStavex_y
290 if (mNumberOfHalfStaves[layer] == 2) { // staggered geometry
291 path += Form("%s%d_%d/", getTRKChipPattern(), layer, halfstave); // TRKChipx_0/1
292 } else if (mNumberOfHalfStaves[layer] == 1) { // turbo geometry
293 path += Form("%s%d_1/", getTRKChipPattern(), layer); // TRKChipx_1
294 }
295 path += Form("%s%d_1/", getTRKSensorPattern(), layer); // TRKSensorx_1
296 }
297 return path;
298}
299
300//__________________________________________________________________________
302{
303 // extract matrix transforming from the PHYSICAL sensor frame to global one
304 // Note, the if the effective sensitive layer thickness is smaller than the
305 // total physical sensor tickness, this matrix is biased and connot be used
306 // directly for transformation from sensor frame to global one.
307 // Therefore we need to add a shift
308
309 auto path = getMatrixPath(index);
310
311 static TGeoHMatrix matTmp;
312 gGeoManager->PushPath(); // Preserve the modeler state.
313
314 if (!gGeoManager->cd(path.Data())) {
315 gGeoManager->PopPath();
316 LOG(error) << "Error in cd-ing to " << path.Data();
317 return nullptr;
318 } // end if !gGeoManager
319
320 matTmp = *gGeoManager->GetCurrentMatrix(); // matrix may change after cd
321
322 // RSS
323 // matTmp.Print();
324 // Restore the modeler state.
325 gGeoManager->PopPath();
326
327 static int chipInGlo{0};
328
330 // account for the difference between physical sensitive layer (where charge collection is simulated) and effective sensor thicknesses
331 // in the VD case this will be accounted by specialized functions during the clusterization (following what it is done for ITS3)
332 // this can be done once the right sensor thickness is in place in the geometry
333 // double delta = 0.;
334 // if (getSubDetID(index) == 1){ /// ML/OT
335 // delta = Segmentation::SensorLayerThicknessVD - Segmentation::SiliconTickness;
336 // static TGeoTranslation tra(0., 0.5 * delta, 0.);
337 // matTmp *= tra;
338 // }
339 // std::cout<<"-----"<<std::endl;
340 // matTmp.Print();
341
342 return &matTmp;
343}
344
345//__________________________________________________________________________
347{
348 if (mSize < 1) {
349 LOG(warning) << "The method Build was not called yet";
350 Build(mask);
351 return;
352 }
353
354 // build matrices
355 if ((mask & o2::math_utils::bit2Mask(o2::math_utils::TransformType::L2G)) && !getCacheL2G().isFilled()) {
356 // Matrices for Local (Sensor!!! rather than the full chip) to Global frame transformation
357 LOGP(info, "Loading {} L2G matrices from TGeo; there are {} matrices", getName(), mSize);
358 auto& cacheL2G = getCacheL2G();
359 cacheL2G.setSize(mSize);
360
361 for (int i = 0; i < mSize; i++) {
362 TGeoHMatrix* hm = extractMatrixSensor(i);
363 cacheL2G.setMatrix(Mat3D(*hm), i);
364 }
365 }
366
367 // TODO: build matrices for the cases T2L, T2G and T2GRot when needed
368}
369
370//__________________________________________________________________________
371
372#ifdef ENABLE_UPGRADES
373const char* GeometryTGeo::composeSymNameLayer(int d, int lr)
374{
375 return Form("%s/%s%d", composeSymNameTRK(d), getTRKLayerPattern(), lr);
376}
377#endif
378
379const char* GeometryTGeo::composeSymNameStave(int d, int lr)
380{
381 return Form("%s/%s%d", composeSymNameLayer(d, lr), getTRKStavePattern(), lr);
382}
383
384const char* GeometryTGeo::composeSymNameChip(int d, int lr)
385{
386 return Form("%s/%s%d", composeSymNameStave(d, lr), getTRKChipPattern(), lr);
387}
388
389const char* GeometryTGeo::composeSymNameSensor(int d, int lr)
390{
391 return Form("%s/%s%d", composeSymNameChip(d, lr), getTRKSensorPattern(), lr);
392}
393
394//__________________________________________________________________________
395int GeometryTGeo::extractVolumeCopy(const char* name, const char* prefix) const
396{
397 TString nms = name;
398 if (!nms.BeginsWith(prefix)) {
399 return -1;
400 }
401 nms.Remove(0, strlen(prefix));
402 if (!isdigit(nms.Data()[0])) {
403 return -1;
404 }
405 return nms.Atoi();
406}
407
408//__________________________________________________________________________
410{
411 int numberOfLayers = 0;
412 TGeoVolume* trkV = gGeoManager->GetVolume(getTRKVolPattern());
413 if (trkV == nullptr) {
414 LOG(fatal) << getName() << " volume " << getTRKVolPattern() << " is not in the geometry";
415 }
416
417 // Loop on all TRKV nodes, count Layer volumes by checking names
418 // Build on the fly layer - wrapper correspondence
419 TObjArray* nodes = trkV->GetNodes();
420 // nodes->Print();
421 int nNodes = nodes->GetEntriesFast();
422 for (int j = 0; j < nNodes; j++) {
423 int lrID = -1;
424 auto nd = dynamic_cast<TGeoNode*>(nodes->At(j));
425 const char* name = nd->GetName();
426 if (strstr(name, getTRKLayerPattern()) != nullptr) {
427 numberOfLayers++;
429 LOG(fatal) << "Failed to extract layer ID from the " << name;
430 }
431 mLayerToWrapper[lrID] = -1; // not wrapped
432 } else if (strstr(name, getTRKWrapVolPattern()) != nullptr) { // this is a wrapper volume, may cointain layers
433 int wrID = -1;
435 LOG(fatal) << "Failed to extract wrapper ID from the " << name;
436 }
437 TObjArray* nodesW = nd->GetNodes();
438 int nNodesW = nodesW->GetEntriesFast();
439
440 for (int jw = 0; jw < nNodesW; jw++) {
441 auto ndW = dynamic_cast<TGeoNode*>(nodesW->At(jw))->GetName();
442 if (strstr(ndW, getTRKLayerPattern()) != nullptr) {
443 if ((lrID = extractVolumeCopy(ndW, GeometryTGeo::getTRKLayerPattern())) < 0) {
444 LOGP(fatal, "Failed to extract layer ID from wrapper volume '{}' from one of its nodes '{}'", name, ndW);
445 }
446 numberOfLayers++;
447 mLayerToWrapper[lrID] = wrID;
448 }
449 }
450 }
451 }
452 return numberOfLayers;
453}
454
455//__________________________________________________________________________
457{
458 int numberOfPetals = 0;
459 TGeoVolume* trkV = gGeoManager->GetVolume(getTRKVolPattern());
460 if (!trkV) {
461 LOGP(fatal, "{} volume {} is not in the geometry", getName(), getTRKVolPattern());
462 return 0;
463 }
464
465 // Loop on all TRKV nodes, count PETAL assemblies and their contents
466 TObjArray* nodes = trkV->GetNodes();
467 if (!nodes) {
468 LOGP(warning, "{} volume has no child nodes", getTRKVolPattern());
469 return 0;
470 }
471
472 LOGP(info, "Searching for petal assemblies in {} (pattern: {})",
474
475 for (int j = 0; j < nodes->GetEntriesFast(); j++) {
476 auto* nd = dynamic_cast<TGeoNode*>(nodes->At(j));
477 const char* name = nd->GetName();
478
479 if (strstr(name, getTRKPetalAssemblyPattern()) != nullptr) {
480 numberOfPetals++;
481 LOGP(info, "Found petal assembly: {}", name);
482
483 // Get petal volume and its nodes for debugging
484 TGeoVolume* petalVol = nd->GetVolume();
485 if (petalVol) {
486 TObjArray* petalNodes = petalVol->GetNodes();
487 if (petalNodes) {
488 LOGP(debug, "Petal {} contains {} child nodes", name, petalNodes->GetEntriesFast());
489 // Print all nodes in this petal
490 for (int k = 0; k < petalNodes->GetEntriesFast(); k++) {
491 auto* petalNode = dynamic_cast<TGeoNode*>(petalNodes->At(k));
492 LOGP(debug, " Node {}: {}", k, petalNode->GetName());
493 }
494 } else {
495 LOGP(warning, "Petal {} has no child nodes", name);
496 }
497 } else {
498 LOGP(warning, "Petal {} has no volume", name);
499 }
500 }
501 }
502
503 if (numberOfPetals == 0) {
504 LOGP(warning, "No petal assemblies found in geometry");
505 } else {
506 LOGP(info, "Found {} petal assemblies", numberOfPetals);
507 }
508
509 return numberOfPetals;
510}
511
512//__________________________________________________________________________
514{
515 // The number of active parts returned here is 36 = 4 petals * (3 layers + 6 disks)
516 int numberOfParts = 0;
517 TGeoVolume* vdV = gGeoManager->GetVolume(getTRKVolPattern());
518 if (!vdV) {
519 LOGP(fatal, "{} volume {} is not in the geometry", getName(), getTRKVolPattern());
520 return 0;
521 }
522
523 // Find first petal to count its active parts
524 TObjArray* nodes = vdV->GetNodes();
525 if (!nodes) {
526 LOGP(warning, "{} volume has no child nodes", getTRKVolPattern());
527 return 0;
528 }
529
530 bool petalFound = false;
531
532 for (int j = 0; j < nodes->GetEntriesFast(); j++) {
533 auto* nd = dynamic_cast<TGeoNode*>(nodes->At(j));
534 const char* name = nd->GetName();
535 if (strstr(name, getTRKPetalAssemblyPattern()) == nullptr) {
536 continue;
537 }
538
539 petalFound = true;
540 LOGP(info, "Counting active parts in petal: {}", name);
541
542 // Found a petal, count its layers and disks
543 TGeoVolume* petalVol = nd->GetVolume();
544 if (!petalVol) {
545 LOGP(warning, "Petal {} has no volume", name);
546 break;
547 }
548
549 TObjArray* petalNodes = petalVol->GetNodes();
550 if (!petalNodes) {
551 LOGP(warning, "Petal {} has no child nodes", name);
552 break;
553 }
554
555 for (int k = 0; k < petalNodes->GetEntriesFast(); k++) {
556 auto* petalNode = dynamic_cast<TGeoNode*>(petalNodes->At(k));
557 const char* nodeName = petalNode->GetName();
558
559 if (strstr(nodeName, getTRKPetalLayerPattern()) != nullptr ||
560 strstr(nodeName, getTRKPetalDiskPattern()) != nullptr) {
561 numberOfParts++;
562 LOGP(debug, "Found active part in {}: {}", name, nodeName);
563 }
564 }
565 // We only need to check one petal as they're identical
566 break;
567 }
568
569 if (!petalFound) {
570 LOGP(warning, "No petal assembly found matching pattern '{}'", getTRKPetalAssemblyPattern());
571 return 0;
572 }
573
574 if (numberOfParts == 0) {
575 LOGP(warning, "No active parts (layers/disks) found in petal");
576 return 0;
577 }
578
579 // Multiply by number of petals since all petals are identical
580 int totalParts = numberOfParts * mNumberOfPetalsVD;
581 LOGP(info, "Total number of active parts: {} ({}*{})",
582 totalParts, numberOfParts, mNumberOfPetalsVD);
583 return totalParts;
584}
585
586//__________________________________________________________________________
588{
589 // Count disks in the first petal (all petals are identical)
590 int numberOfDisks = 0;
591 TGeoVolume* vdV = gGeoManager->GetVolume(getTRKVolPattern());
592 if (!vdV) {
593 LOGP(fatal, "{} volume {} is not in the geometry", getName(), getTRKVolPattern());
594 return 0;
595 }
596
597 // Find first petal
598 TObjArray* nodes = vdV->GetNodes();
599 if (!nodes) {
600 LOGP(warning, "{} volume has no child nodes", getTRKVolPattern());
601 return 0;
602 }
603
604 bool petalFound = false;
605
606 for (int j = 0; j < nodes->GetEntriesFast(); j++) {
607 auto* nd = dynamic_cast<TGeoNode*>(nodes->At(j));
608 if (strstr(nd->GetName(), getTRKPetalAssemblyPattern()) == nullptr) {
609 continue;
610 }
611
612 petalFound = true;
613 LOGP(info, "Counting disks in petal: {}", nd->GetName());
614
615 // Count disks in this petal
616 TGeoVolume* petalVol = nd->GetVolume();
617 if (!petalVol) {
618 LOGP(warning, "Petal {} has no volume", nd->GetName());
619 break;
620 }
621
622 TObjArray* petalNodes = petalVol->GetNodes();
623 if (!petalNodes) {
624 LOGP(warning, "Petal {} has no child nodes", nd->GetName());
625 break;
626 }
627
628 for (int k = 0; k < petalNodes->GetEntriesFast(); k++) {
629 auto* petalNode = dynamic_cast<TGeoNode*>(petalNodes->At(k));
630 if (strstr(petalNode->GetName(), getTRKPetalDiskPattern()) != nullptr) {
631 numberOfDisks++;
632 LOGP(info, "Found disk in {} : {}", nd->GetName(), petalNode->GetName());
633 }
634 }
635 // One petal is enough
636 break;
637 }
638
639 if (!petalFound) {
640 LOGP(warning, "No petal assembly found matching pattern '{}'", getTRKPetalAssemblyPattern());
641 }
642
643 if (numberOfDisks == 0) {
644 LOGP(warning, "No disks found in VD geometry");
645 }
646
647 return numberOfDisks;
648}
649
650//__________________________________________________________________________
652{
653 // Count layers in the first petal (all petals are identical)
654 int numberOfLayers = 0;
655 TGeoVolume* vdV = gGeoManager->GetVolume(getTRKVolPattern());
656 if (!vdV) {
657 LOGP(fatal, "{} volume {} is not in the geometry", getName(), getTRKVolPattern());
658 return 0;
659 }
660
661 // Find first petal
662 TObjArray* nodes = vdV->GetNodes();
663 if (!nodes) {
664 LOGP(warning, "{} volume has no child nodes", getTRKVolPattern());
665 return 0;
666 }
667
668 bool petalFound = false;
669
670 for (int j = 0; j < nodes->GetEntriesFast(); j++) {
671 auto* nd = dynamic_cast<TGeoNode*>(nodes->At(j));
672 if (strstr(nd->GetName(), getTRKPetalAssemblyPattern()) == nullptr) {
673 continue;
674 }
675
676 petalFound = true;
677 LOGP(info, "Counting layers in petal: {}", nd->GetName());
678
679 // Count layers in this petal
680 TGeoVolume* petalVol = nd->GetVolume();
681 if (!petalVol) {
682 LOGP(warning, "Petal {} has no volume", nd->GetName());
683 break;
684 }
685
686 TObjArray* petalNodes = petalVol->GetNodes();
687 if (!petalNodes) {
688 LOGP(warning, "Petal {} has no child nodes", nd->GetName());
689 break;
690 }
691
692 for (int k = 0; k < petalNodes->GetEntriesFast(); k++) {
693 auto* petalNode = dynamic_cast<TGeoNode*>(petalNodes->At(k));
694 if (strstr(petalNode->GetName(), getTRKPetalLayerPattern()) != nullptr) {
695 numberOfLayers++;
696 LOGP(info, "Found layer in {} : {}", nd->GetName(), petalNode->GetName());
697 }
698 }
699 // One petal is enough
700 break;
701 }
702
703 if (!petalFound) {
704 LOGP(warning, "No petal assembly found matching pattern '{}'", getTRKPetalAssemblyPattern());
705 }
706
707 if (numberOfLayers == 0) {
708 LOGP(warning, "No layers found in VD geometry");
709 }
710
711 return numberOfLayers;
712}
713
714//__________________________________________________________________________
716{
717 // The number of chips per petal returned here is 9 for each layer = number of layers + number of quarters of disks per petal
718 int numberOfChips = 0;
719 TGeoVolume* vdV = gGeoManager->GetVolume(getTRKVolPattern());
720 if (!vdV) {
721 LOGP(fatal, "{} volume {} is not in the geometry", getName(), getTRKVolPattern());
722 return 0;
723 }
724
725 // Find first petal assembly
726 TObjArray* nodes = vdV->GetNodes();
727 if (!nodes) {
728 LOGP(warning, "{} volume has no child nodes", getTRKVolPattern());
729 return 0;
730 }
731
732 bool petalFound = false;
733
734 for (int j = 0; j < nodes->GetEntriesFast(); j++) {
735 auto* nd = dynamic_cast<TGeoNode*>(nodes->At(j));
736 const char* name = nd->GetName();
737 if (strstr(name, getTRKPetalAssemblyPattern()) == nullptr) {
738 continue;
739 }
740
741 petalFound = true;
742 LOGP(info, "Counting chips in petal: {}", name);
743
744 // Found a petal, count sensors in its layers and disks
745 TGeoVolume* petalVol = nd->GetVolume();
746 if (!petalVol) {
747 LOGP(warning, "Petal {} has no volume", name);
748 break;
749 }
750
751 TObjArray* petalNodes = petalVol->GetNodes();
752 if (!petalNodes) {
753 LOGP(warning, "Petal {} has no child nodes", name);
754 break;
755 }
756
757 for (int k = 0; k < petalNodes->GetEntriesFast(); k++) {
758 auto* petalNode = dynamic_cast<TGeoNode*>(petalNodes->At(k));
759 const char* nodeName = petalNode->GetName();
760 TGeoVolume* vol = petalNode->GetVolume();
761
762 if (!vol) {
763 LOGP(debug, "Node {} has no volume", nodeName);
764 continue;
765 }
766
767 // Look for sensors in this volume
768 TObjArray* subNodes = vol->GetNodes();
769 if (!subNodes) {
770 LOGP(debug, "Node {} has no sub-nodes", nodeName);
771 continue;
772 }
773
774 for (int i = 0; i < subNodes->GetEntriesFast(); i++) {
775 auto* subNode = dynamic_cast<TGeoNode*>(subNodes->At(i));
776 if (strstr(subNode->GetName(), getTRKSensorPattern()) != nullptr) {
777 numberOfChips++;
778 LOGP(debug, "Found sensor in {}: {}", nodeName, subNode->GetName());
779 }
780 }
781 }
782 // We only need one petal
783 break;
784 }
785
786 if (!petalFound) {
787 LOGP(warning, "No petal assembly found matching pattern '{}'", getTRKPetalAssemblyPattern());
788 }
789
790 if (numberOfChips == 0) {
791 LOGP(warning, "No chips/sensors found in VD petal");
792 }
793
794 LOGP(info, "Number of chips per petal: {}", numberOfChips);
795 return numberOfChips;
796}
797
798//__________________________________________________________________________
800{
801 int numberOfStaves = 0;
802
803 std::string layName = Form("%s%d", getTRKLayerPattern(), lay);
804 TGeoVolume* layV = gGeoManager->GetVolume(layName.c_str());
805
806 if (layV == nullptr) {
807 LOG(fatal) << getName() << " volume " << getTRKLayerPattern() << " is not in the geometry";
808 }
809
810 // Loop on all layV nodes, count Layer volumes by checking names
811 TObjArray* nodes = layV->GetNodes();
812 // std::cout << "Printing nodes for layer " << lay << std::endl;
813 // nodes->Print();
814 int nNodes = nodes->GetEntriesFast();
815
816 for (int j = 0; j < nNodes; j++) {
817 int lrID = -1;
818 auto nd = dynamic_cast<TGeoNode*>(nodes->At(j));
819 const char* name = nd->GetName();
820 if (strstr(name, getTRKStavePattern()) != nullptr) {
821 numberOfStaves++;
822 }
823 }
824 return numberOfStaves;
825}
826
827//__________________________________________________________________________
829{
830 int numberOfHalfStaves = 0;
831
832 std::string staveName = Form("%s%d", getTRKStavePattern(), lay);
833 TGeoVolume* staveV = gGeoManager->GetVolume(staveName.c_str());
834
835 if (staveV == nullptr) {
836 LOG(fatal) << getName() << " volume " << getTRKStavePattern() << " is not in the geometry";
837 }
838
839 // Loop on all layV nodes, count Layer volumes by checking names
840 TObjArray* nodes = staveV->GetNodes();
841 // std::cout << "Printing nodes for layer " << lay << std::endl;
842 // nodes->Print();
843 int nNodes = nodes->GetEntriesFast();
844
845 for (int j = 0; j < nNodes; j++) {
846 auto nd = dynamic_cast<TGeoNode*>(nodes->At(j));
847 const char* name = nd->GetName();
848 if (strstr(name, getTRKChipPattern()) != nullptr) {
849 numberOfHalfStaves++;
850 }
851 }
852 return numberOfHalfStaves;
853}
854
855//__________________________________________________________________________
856void GeometryTGeo::PrintChipID(int index, int subDetID, int petalcase, int disk, int lay, int stave, int halfstave) const
857{
858 std::cout << "\nindex = " << index << std::endl;
859 std::cout << "subDetID = " << subDetID << std::endl;
860 std::cout << "petalcase = " << petalcase << std::endl;
861 std::cout << "layer = " << lay << std::endl;
862 std::cout << "disk = " << disk << std::endl;
863 std::cout << "first chip index = " << getFirstChipIndex(lay, petalcase, subDetID) << std::endl;
864 std::cout << "stave = " << stave << std::endl;
865 std::cout << "halfstave = " << halfstave << std::endl;
866}
867
868//__________________________________________________________________________
869void GeometryTGeo::Print(Option_t*) const
870{
871 if (!isBuilt()) {
872 LOGF(info, "Geometry not built yet!");
873 return;
874 }
875 std::cout << "Detector ID: " << sInstance.get()->getDetID() << std::endl;
876
877 LOGF(info, "Summary of GeometryTGeo: %s", getName());
878 LOGF(info, "Number of layers ML + OL: %d", mNumberOfLayersMLOT);
879 LOGF(info, "Number of active parts VD: %d", mNumberOfActivePartsVD);
880 LOGF(info, "Number of layers VD: %d", mNumberOfLayersVD);
881 LOGF(info, "Number of petals VD: %d", mNumberOfPetalsVD);
882 LOGF(info, "Number of disks VD: %d", mNumberOfDisksVD);
883 LOGF(info, "Number of chips per petal VD: ");
884 for (int i = 0; i < mNumberOfPetalsVD; i++) {
885 LOGF(info, "%d", mNumberOfChipsPerPetalVD[i]);
886 }
887 LOGF(info, "Number of staves and half staves per layer MLOT: ");
888 for (int i = 0; i < mNumberOfLayersMLOT; i++) {
889 std::string mlot = "";
890 mlot = (i < 4) ? "ML" : "OT";
891 LOGF(info, "Layer: %d, %s, %d staves, %d half staves per stave", i, mlot.c_str(), mNumberOfStaves[i], mNumberOfHalfStaves[i]);
892 }
893 LOGF(info, "Total number of chips: %d", getNumberOfChips());
894
895 std::cout << "mLastChipIndex = [";
896 for (int i = 0; i < mLastChipIndex.size(); i++) {
897 std::cout << mLastChipIndex[i];
898 if (i < mLastChipIndex.size() - 1) {
899 std::cout << ", ";
900 }
901 }
902 std::cout << "]" << std::endl;
903 std::cout << "mLastChipIndexVD = [";
904 for (int i = 0; i < mLastChipIndexVD.size(); i++) {
905 std::cout << mLastChipIndexVD[i];
906 if (i < mLastChipIndexVD.size() - 1) {
907 std::cout << ", ";
908 }
909 }
910 std::cout << "]" << std::endl;
911}
912
913} // namespace trk
914} // namespace o2
int32_t i
uint32_t j
Definition RawData.h:0
Definition of the SegmentationChipclass.
std::ostringstream debug
Static class with identifiers, bitmasks and names for ALICE detectors.
Definition DetID.h:58
const char * getName() const
int mSize
prebooked number of sensors
const MatrixCache< Mat3D > & getCacheL2G() const
static const char * getTRKPetalDiskPattern()
static std::string sPetalAssemblyName
static const char * getTRKStavePattern()
int getPetalCase(int index) const
static const char * getTRKChipPattern()
std::vector< int > mNumberOfChipsPerLayerVD
number of chips per layer VD ( = number of petals)
static std::string sVolumeName
int getSubDetID(int index) const
std::array< char, MAXLAYERS > mLayerToWrapper
Layer to wrapper correspondence.
static std::string sPetalLayerName
static const char * getTRKSensorPattern()
static std::string sStaveName
std::vector< int > mNumberOfHalfStaves
Number Of Staves in each stave of the layer in ML/OT.
int extractNumberOfChipsPerPetalVD() const
int extractNumberOfHalfStavesMLOT(int lay) const
static const char * getTRKPetalLayerPattern()
int getChipIndex(int subDetID, int petalcase, int disk, int lay, int stave, int halfstave) const
int extractNumberOfLayersMLOT()
Determines the number of active parts in the Geometry.
std::vector< int > mNumbersOfChipPerDiskVD
numbersOfChipPerDiskVD
std::vector< int > mNumberOfStaves
Number Of Staves per layer in ML/OT.
Int_t mNumberOfPetalsVD
number of Petals = chip in each VD layer
std::vector< int > mLastChipIndexVD
max ID of the detctor in the layer for the VD
static std::string sPetalName
int extractNumberOfStavesMLOT(int lay) const
static const char * composeSymNameChip(int d, int lr)
static std::string sPetalDiskName
void Print(Option_t *opt="") const
void PrintChipID(int index, int subDetID, int petalcase, int disk, int lay, int stave, int halfstave) const
int getLayer(int index) const
static const char * getTRKWrapVolPattern()
TString getMatrixPath(int index) const
static const char * getTRKPetalAssemblyPattern()
int getNumberOfChips() const
static const char * getTRKLayerPattern()
int getFirstChipIndex(int lay, int petalcase, int subDetID) const
o2::math_utils::Transform3D Mat3D
static std::string sWrapperVolumeName
Wrapper volume name.
int extractNumberOfLayersVD() const
std::vector< int > mNumberOfChipsPerPetalVD
numbersOfChipPerPetalVD
std::vector< int > mLastChipIndex
max ID of the detctor in the petal(VD) or layer(MLOT)
static std::string sChipName
static std::string sSensorName
bool getChipID(int index, int &subDetID, int &petalcase, int &disk, int &lay, int &stave, int &halfstave) const
std::vector< int > mLastChipIndexMLOT
max ID of the detctor in the layer for the MLOT
void fillMatrixCache(int mask)
static std::string sLayerName
int extractNumberOfActivePartsVD() const
static const char * composeSymNameSensor(int d, int layer)
int extractNumberOfDisksVD() const
static const char * getTRKPetalPattern()
Int_t mNumberOfActivePartsVD
number of layers
std::vector< int > mNumberOfChipsPerLayerMLOT
number of chips per layer MLOT ( = 1 for the moment)
Int_t mNumberOfDisksVD
number of Disks = 6
Int_t mNumberOfLayersMLOT
number of layers
static const char * composeSymNameLayer(int d, int layer)
int getStave(int index) const
static const char * getTRKVolPattern()
static const char * composeSymNameStave(int d, int layer)
int getDisk(int index) const
int extractNumberOfPetalsVD() const
int extractVolumeCopy(const char *name, const char *prefix) const
Extract number following the prefix in the name string.
void Build(int loadTrans)
Int_t mNumberOfLayersVD
number of layers
int getHalfStave(int index) const
GeometryTGeo(bool build=false, int loadTrans=0)
TGeoHMatrix * extractMatrixSensor(int index) const
GLuint index
Definition glcorearb.h:781
GLuint const GLchar * name
Definition glcorearb.h:781
GLsizei const GLchar *const * path
Definition glcorearb.h:3591
GLenum GLuint GLint GLint layer
Definition glcorearb.h:1310
GLint GLuint mask
Definition glcorearb.h:291
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
static constexpr int L2G
Definition Cartesian.h:54
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"