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
16
17// ATTENTION: In opposite to old AliITSgeomTGeo, all indices start from 0, not from 1!!!
18
19#include <fairlogger/Logger.h> // for LOG
23#include "MathUtils/Cartesian.h"
24
25#ifdef ENABLE_UPGRADES
26#include "ITS3Base/SpecsV2.h"
29#endif
30
31#include <TGeoBBox.h> // for TGeoBBox
32#include <TGeoManager.h> // for gGeoManager, TGeoManager
33#include <TGeoPhysicalNode.h> // for TGeoPNEntry, TGeoPhysicalNode
34#include <TGeoShape.h> // for TGeoShape
35#include <TMath.h> // for Nint, ATan2, RadToDeg
36#include <TString.h> // for TString, Form
37#include "TClass.h" // for TClass
38#include "TGeoMatrix.h" // for TGeoHMatrix
39#include "TGeoNode.h" // for TGeoNode, TGeoNodeMatrix
40#include "TGeoVolume.h" // for TGeoVolume
41#include "TMathBase.h" // for Max
42#include "TObjArray.h" // for TObjArray
43#include "TObject.h" // for TObject
44
45#include <cctype> // for isdigit
46#include <cstdio> // for snprintf, NULL, printf
47#include <cstring> // for strstr, strlen
48#include <algorithm>
49
50using namespace TMath;
51using namespace o2::its;
52using namespace o2::detectors;
53
55
57
58std::unique_ptr<o2::its::GeometryTGeo> GeometryTGeo::sInstance;
60{
61 if (!mOwner) {
62 mOwner = true;
63 sInstance.release();
64 }
65}
66
67std::string GeometryTGeo::sVolumeName = "ITSV";
68std::string GeometryTGeo::sLayerName = "ITSULayer";
69std::string GeometryTGeo::sHalfBarrelName = "ITSUHalfBarrel";
70std::string GeometryTGeo::sStaveName = "ITSUStave";
71std::string GeometryTGeo::sHalfStaveName = "ITSUHalfStave";
72std::string GeometryTGeo::sModuleName = "ITSUModule";
73std::string GeometryTGeo::sChipName = "ITSUChip";
74std::string GeometryTGeo::sSensorName = "ITSUSensor";
75std::string GeometryTGeo::sWrapperVolumeName = "ITSUWrapVol";
76
77const std::string GeometryTGeo::sLayerNameITS3 = "ITS3Layer";
78const std::string GeometryTGeo::sHalfBarrelNameITS3 = "ITS3CarbonForm";
79const std::string GeometryTGeo::sStaveNameITS3 = "ITS3Chip";
80const std::string GeometryTGeo::sHalfStaveNameITS3 = "ITS3Segment";
81const std::string GeometryTGeo::sModuleNameITS3 = "ITS3RSU";
82const std::string GeometryTGeo::sChipNameITS3 = "ITS3Tile";
83const std::string GeometryTGeo::sSensorNameITS3 = "ITS3PixelArray";
84
85//__________________________________________________________________________
86GeometryTGeo::GeometryTGeo(bool build, int loadTrans) : o2::itsmft::GeometryTGeo(DetID::ITS)
87{
88 // default c-tor, if build is true, the structures will be filled and the transform matrices
89 // will be cached
90 if (sInstance) {
91 LOG(fatal) << "Invalid use of public constructor: o2::its::GeometryTGeo instance exists";
92 // throw std::runtime_error("Invalid use of public constructor: o2::its::GeometryTGeo instance exists");
93 }
94
95 mLayerToWrapper.fill(-1);
96 if (build) {
97 Build(loadTrans);
98 }
99}
100
101//__________________________________________________________________________
102void GeometryTGeo::adopt(GeometryTGeo* raw, bool canDelete)
103{
104 // adopt the unique instance from external raw pointer (to be used only to read saved instance from file)
105 if (sInstance) {
106 LOG(fatal) << "No adoption: o2::its::GeometryTGeo instance exists";
107 }
108 sInstance = std::unique_ptr<o2::its::GeometryTGeo>(raw);
109 sInstance->mOwner = canDelete;
110}
111
112//__________________________________________________________________________
113int GeometryTGeo::getChipIndex(int lay, int hba, int sta, int chipInStave) const
114{
115 return getFirstChipIndex(lay) + mNumberOfChipsPerHalfBarrel[lay] * hba + mNumberOfChipsPerStave[lay] * sta + chipInStave;
116}
117
118//__________________________________________________________________________
119int GeometryTGeo::getChipIndex(int lay, int hba, int sta, int substa, int chipInSStave) const
120{
121 int n = getFirstChipIndex(lay) + mNumberOfChipsPerHalfBarrel[lay] * hba + mNumberOfChipsPerStave[lay] * sta + chipInSStave;
122 if (mNumberOfHalfStaves[lay] && substa > 0) {
123 n += mNumberOfChipsPerHalfStave[lay] * substa;
124 }
125 return n;
126}
127
128//__________________________________________________________________________
129int GeometryTGeo::getChipIndex(int lay, int hba, int sta, int substa, int md, int chipInMod) const
130{
131 if (mNumberOfHalfStaves[lay] == 0) {
132 return getChipIndex(lay, substa, md, chipInMod);
133 } else {
134 int n = getFirstChipIndex(lay) + mNumberOfChipsPerHalfBarrel[lay] * hba + mNumberOfChipsPerStave[lay] * sta + chipInMod;
135 if (mNumberOfHalfStaves[lay] && substa > 0) {
136 n += mNumberOfChipsPerHalfStave[lay] * substa;
137 }
138 if (mNumberOfModules[lay] && md > 0) {
139 n += mNumberOfChipsPerModule[lay] * md;
140 }
141 return n;
142 }
143}
144
145//__________________________________________________________________________
146bool GeometryTGeo::getLayer(int index, int& lay, int& indexInLr) const
147{
148 lay = getLayer(index);
149 indexInLr = index - getFirstChipIndex(lay);
150 return kTRUE;
151}
152
153//__________________________________________________________________________
155{
156 int lay = 0;
157 while (index > mLastChipIndex[lay]) {
158 lay++;
159 }
160 return lay;
161}
162
163//__________________________________________________________________________
165{
166 int lay = 0;
167 while (index > mLastChipIndex[lay]) {
168 lay++;
169 }
170 index -= getFirstChipIndex(lay);
172}
173
174//__________________________________________________________________________
176{
177 int lay = 0;
178 while (index > mLastChipIndex[lay]) {
179 lay++;
180 }
181 index -= getFirstChipIndex(lay);
182 return index / mNumberOfChipsPerStave[lay];
183}
184
185//__________________________________________________________________________
187{
188 int lay = 0;
189 while (index > mLastChipIndex[lay]) {
190 lay++;
191 }
192 if (mNumberOfHalfStaves[lay] < 0) {
193 return -1;
194 }
195 index -= getFirstChipIndex(lay);
197 return index / mNumberOfChipsPerHalfStave[lay];
198}
199
200//__________________________________________________________________________
202{
203 int lay = 0;
204 while (index > mLastChipIndex[lay]) {
205 lay++;
206 }
207 if (mNumberOfModules[lay] < 0) {
208 return 0;
209 }
210 index -= getFirstChipIndex(lay);
212 if (mNumberOfHalfStaves[lay] != 0) {
214 }
215 return index / mNumberOfChipsPerModule[lay];
216}
217
218//__________________________________________________________________________
220{
221 int lay = 0;
222 while (index > mLastChipIndex[lay]) {
223 lay++;
224 }
225 index -= getFirstChipIndex(lay);
226 return index;
227}
228
229//__________________________________________________________________________
231{
232 int lay = 0;
233 while (index > mLastChipIndex[lay]) {
234 lay++;
235 }
236 index -= getFirstChipIndex(lay);
237 return index % mNumberOfChipsPerStave[lay];
238}
239
240//__________________________________________________________________________
242{
243 int lay = 0;
244 while (index > mLastChipIndex[lay]) {
245 lay++;
246 }
247 index -= getFirstChipIndex(lay);
248 return index % mNumberOfChipsPerHalfStave[lay];
249}
250
251//__________________________________________________________________________
253{
254 int lay = 0;
255 while (index > mLastChipIndex[lay]) {
256 lay++;
257 }
258 index -= getFirstChipIndex(lay);
259 return index % mNumberOfChipsPerModule[lay];
260}
261
262//__________________________________________________________________________
263bool GeometryTGeo::getChipId(int index, int& lay, int& sta, int& hsta, int& mod, int& chip) const
264{
265 lay = getLayer(index);
266 index -= getFirstChipIndex(lay);
267 sta = index / mNumberOfChipsPerStave[lay];
269 hsta = mNumberOfHalfStaves[lay] > 0 ? index / mNumberOfChipsPerHalfStave[lay] : -1;
271 mod = mNumberOfModules[lay] > 0 ? index / mNumberOfChipsPerModule[lay] : -1;
272 chip = index % mNumberOfChipsPerModule[lay];
273
274 return kTRUE;
275}
276
277//__________________________________________________________________________
278bool GeometryTGeo::getChipId(int index, int& lay, int& hba, int& sta, int& hsta, int& mod, int& chip) const
279{
280 lay = getLayer(index);
281 index -= getFirstChipIndex(lay);
284 sta = index / mNumberOfChipsPerStave[lay];
286 hsta = mNumberOfHalfStaves[lay] > 0 ? index / mNumberOfChipsPerHalfStave[lay] : -1;
288 mod = mNumberOfModules[lay] > 0 ? index / mNumberOfChipsPerModule[lay] : -1;
289 chip = index % mNumberOfChipsPerModule[lay];
290
291 return kTRUE;
292}
293
294//__________________________________________________________________________
295const char* GeometryTGeo::composeSymNameITS(bool isITS3)
296{
297 if (isITS3) {
298#ifdef ENABLE_UPGRADES
299 return o2::detectors::DetID(o2::detectors::DetID::IT3).getName();
300#endif
301 }
302
304}
305
306//__________________________________________________________________________
307const char* GeometryTGeo::composeSymNameLayer(int lr, bool isITS3)
308{
309 return Form("%s/%s%d", composeSymNameITS(), isITS3 ? getITS3LayerPattern() : getITSLayerPattern(), lr);
310}
311
312//__________________________________________________________________________
313const char* GeometryTGeo::composeSymNameHalfBarrel(int lr, int hbarrel, bool isITS3)
314{
315 return hbarrel >= 0 ? Form("%s/%s%d", composeSymNameLayer(lr, isITS3), isITS3 ? getITS3HalfBarrelPattern() : getITSHalfBarrelPattern(), hbarrel)
317}
318
319//__________________________________________________________________________
320const char* GeometryTGeo::composeSymNameStave(int lr, int hbarrel, int stave, bool isITS3)
321{
322 return Form("%s/%s%d", composeSymNameHalfBarrel(lr, hbarrel, isITS3), isITS3 ? getITS3StavePattern() : getITSStavePattern(), stave);
323}
324
325//__________________________________________________________________________
326const char* GeometryTGeo::composeSymNameHalfStave(int lr, int hba, int stave, int substave, bool isITS3)
327{
328 return substave >= 0 ? Form("%s/%s%d", composeSymNameStave(lr, hba, stave, isITS3), isITS3 ? getITS3HalfStavePattern() : getITSHalfStavePattern(), substave)
329 : composeSymNameStave(lr, hba, stave, isITS3);
330}
331
332//__________________________________________________________________________
333const char* GeometryTGeo::composeSymNameModule(int lr, int hba, int stave, int substave, int mod, bool isITS3)
334{
335 return mod >= 0 ? Form("%s/%s%d", composeSymNameHalfStave(lr, hba, stave, substave, isITS3), isITS3 ? getITS3ModulePattern() : getITSModulePattern(), mod)
336 : composeSymNameHalfStave(lr, hba, stave, substave, isITS3);
337}
338
339//__________________________________________________________________________
340const char* GeometryTGeo::composeSymNameChip(int lr, int hba, int sta, int substave, int mod, int chip, bool isITS3)
341{
342 return Form("%s/%s%d", composeSymNameModule(lr, hba, sta, substave, mod, isITS3), isITS3 ? getITS3ChipPattern() : getITSChipPattern(), chip);
343}
344
346{
347 int lay, hba, stav, sstav, mod, chipInMod;
348 getChipId(index, lay, hba, stav, sstav, mod, chipInMod);
349
350 int wrID = mLayerToWrapper[lay];
351
352 TString path = Form("/cave_1/barrel_1/%s_2/", GeometryTGeo::getITSVolPattern());
353
354 if (wrID >= 0) {
355 path += Form("%s%d_1/", getITSWrapVolPattern(), wrID);
356 }
357
358 if (!mIsLayerITS3[lay]) {
359 path +=
360 Form("%s%d_1/", getITSLayerPattern(), lay);
361 if (mNumberOfHalfBarrels > 0) {
362 path += Form("%s%d_%d/", getITSHalfBarrelPattern(), lay, hba);
363 }
364 path +=
365 Form("%s%d_%d/", getITSStavePattern(), lay, stav);
366
367 if (mNumberOfHalfStaves[lay] > 0) {
368 path += Form("%s%d_%d/", getITSHalfStavePattern(), lay, sstav);
369 }
370 if (mNumberOfModules[lay] > 0) {
371 path += Form("%s%d_%d/", getITSModulePattern(), lay, mod);
372 }
373 path += Form("%s%d_%d/%s%d_1", getITSChipPattern(), lay, chipInMod, getITSSensorPattern(), lay);
374 } else {
375 // hba = carbonform
376 // stav = 0
377 // sstav = segment
378 // mod = rsu
379 // chipInMod = tile
380 // sensor = pixelarray
381 path += Form("%s_0/", getITS3LayerPattern(lay));
382 path += Form("%s_%d/", getITS3CarbonFormPattern(lay), hba);
383 path += Form("%s_0/", getITS3ChipPattern(lay));
384 path += Form("%s_%d/", getITS3SegmentPattern(lay), sstav);
385 path += Form("%s_%d/", getITS3RSUPattern(lay), mod);
386 path += Form("%s_%d/", getITS3TilePattern(lay), chipInMod);
387 path += Form("%s_0", getITS3PixelArrayPattern(lay));
388 }
389 return path;
390}
391
392//__________________________________________________________________________
394{
395 // extract matrix transforming from the PHYSICAL sensor frame to global one
396 // Note, the if the effective sensitive layer thickness is smaller than the
397 // total physical sensor tickness, this matrix is biased and connot be used
398 // directly for transformation from sensor frame to global one.
399 //
400 // Therefore we need to add a shift
401 auto path = getMatrixPath(index);
402
403 static TGeoHMatrix matTmp;
404 gGeoManager->PushPath();
405
406 if (!gGeoManager->cd(path.Data())) {
407 gGeoManager->PopPath();
408 LOG(error) << "Error in cd-ing to " << path.Data();
409 return nullptr;
410 } // end if !gGeoManager
411
412 matTmp = *gGeoManager->GetCurrentMatrix(); // matrix may change after cd
413
414 // RSS
415 // printf("%d/%d/%d %s\n", lay, stav, detInSta, path.Data());
416 // matTmp.Print();
417 // Restore the modeler state.
418 gGeoManager->PopPath();
419
420 static int chipInGlo{0};
421
422 // account for the difference between physical sensitive layer (where charge collection is simulated) and effective sensor thicknesses
424#ifdef ENABLE_UPGRADES
427 }
428#endif
429
430 static TGeoTranslation tra(0., 0.5 * delta, 0.);
431
432 matTmp *= tra;
433
434 return &matTmp;
435}
436
437//__________________________________________________________________________
439{
440 // create for sensor isn the TGeo matrix for Tracking to Local frame transformations
441 static TGeoHMatrix t2l;
442 t2l.Clear();
443 t2l.RotateZ(alpha * RadToDeg()); // rotate in direction of normal to the tangent to the cylinder
444 const TGeoHMatrix& matL2G = getMatrixL2G(isn);
445 const auto& matL2Gi = matL2G.Inverse();
446 t2l.MultiplyLeft(&matL2Gi);
447 return Mat3D(t2l);
448}
449
450//__________________________________________________________________________
451void GeometryTGeo::Build(int loadTrans)
452{
453 if (isBuilt()) {
454 LOG(warning) << "Already built";
455 return; // already initialized
456 }
457
458 if (gGeoManager == nullptr) {
459 // RSTODO: in future there will be a method to load matrices from the CDB
460 LOG(fatal) << "Geometry is not loaded";
461 }
462
463 mIsLayerITS3.fill(false);
465 if (mNumberOfLayers == 0) {
466 return;
467 }
468
479 int numberOfChips = 0;
480
482 for (int i = 0; i < mNumberOfLayers; i++) {
491 numberOfChips += mNumberOfChipsPerLayer[i];
492 mLastChipIndex[i] = numberOfChips - 1;
493 }
494
495 LOGP(debug, "Summary of extracted Geometry:");
496 LOGP(debug, " There are {} Layers and {} HalfBarrels", mNumberOfLayers, mNumberOfHalfBarrels);
497 for (int i = 0; i < mNumberOfLayers; i++) {
498 LOGP(debug, " Layer {}: {:*^30}", i, "START");
499 LOGP(debug, " - mNumberOfStaves={}", mNumberOfStaves[i]);
500 LOGP(debug, " - mNumberOfChipsPerStave={}", mNumberOfChipsPerStave[i]);
501 LOGP(debug, " - mNumberOfHalfStaves={}", mNumberOfHalfStaves[i]);
502 LOGP(debug, " - mNumberOfChipsPerHalfStave={}", mNumberOfChipsPerHalfStave[i]);
503 LOGP(debug, " - mNumberOfModules={}", mNumberOfModules[i]);
504 LOGP(debug, " - mNumberOfChipsPerModules={}", mNumberOfChipsPerModule[i]);
505 LOGP(debug, " - mNumberOfChipsPerLayer={}", mNumberOfChipsPerLayer[i]);
506 LOGP(debug, " - mNumberOfChipsPerHalfBarrel={}", mNumberOfChipsPerHalfBarrel[i]);
507 LOGP(debug, " - mLastChipIndex={}", mLastChipIndex[i]);
508 LOGP(debug, " Layer {}: {:*^30}", i, "END");
509 }
510 LOGP(debug, "In total there {} chips registered", numberOfChips);
511
512#ifdef ENABLE_UPGRADES
513 if (std::any_of(mIsLayerITS3.cbegin(), mIsLayerITS3.cend(), [](auto b) { return b; })) {
514 LOGP(info, "Found active IT3 layers -> Renaming Detector ITS to IT3");
515 mDetID = DetID::IT3;
516 }
517#endif
518
519 setSize(numberOfChips);
521 fillMatrixCache(loadTrans);
522}
523
524//__________________________________________________________________________
526{
527 // populate matrix cache for requested transformations
528 //
529 if (mSize < 1) {
530 LOG(warning) << "The method Build was not called yet";
531 Build(mask);
532 return;
533 }
534
535 // build matrices
536 if ((mask & o2::math_utils::bit2Mask(o2::math_utils::TransformType::L2G)) && !getCacheL2G().isFilled()) {
537 // Matrices for Local (Sensor!!! rather than the full chip) to Global frame transformation
538 LOGP(info, "Loading {} L2G matrices from TGeo; there are {} matrices", getName(), mSize);
539 auto& cacheL2G = getCacheL2G();
540 cacheL2G.setSize(mSize);
541
542 for (int i = 0; i < mSize; i++) {
543 TGeoHMatrix* hm = extractMatrixSensor(i);
544 cacheL2G.setMatrix(Mat3D(*hm), i);
545 }
546 }
547
548 if ((mask & o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L)) && !getCacheT2L().isFilled()) {
549 // matrices for Tracking to Local (Sensor!!! rather than the full chip) frame transformation
550 LOGP(info, "Loading {} T2L matrices from TGeo", getName());
551 auto& cacheT2L = getCacheT2L();
552 cacheT2L.setSize(mSize);
553 for (int i = 0; i < mSize; i++) {
554 TGeoHMatrix& hm = createT2LMatrix(i);
555 cacheT2L.setMatrix(Mat3D(hm), i);
556 }
557 }
558
559 if ((mask & o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2GRot)) && !getCacheT2GRot().isFilled()) {
560 // 2D rotation matrices for Tracking frame to Global rotations
561 LOGP(info, "Loading {} T2G rotation 2D matrices", getName());
562 auto& cacheT2Gr = getCacheT2GRot();
563 cacheT2Gr.setSize(mSize);
564 for (int i = 0; i < mSize; i++) {
565 cacheT2Gr.setMatrix(Rot2D(getSensorRefAlpha(i)), i);
566 }
567 }
568
569 if ((mask & o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2G)) && !getCacheT2G().isFilled()) {
570 LOG(debug) << "It is faster to use 2D rotation for T2G instead of full Transform3D matrices";
571 // matrices for Tracking to Global frame transformation
572 LOGP(info, "Creating {} T2G matrices from TGeo", getName());
573 auto& cacheT2G = getCacheT2G();
574 cacheT2G.setSize(mSize);
575
576 for (int i = 0; i < mSize; i++) {
577 /*
578 TGeoHMatrix& mat = createT2LMatrix(i);
579 mat.MultiplyLeft(extractMatrixSensor(i));
580 */
582 Mat3D mat{};
583 mat.SetComponents(r.getCos(), -r.getSin(), 0., 0., r.getSin(), r.getCos(), 0., 0., 0., 0., 1., 0.);
584 cacheT2G.setMatrix(mat, i);
585 }
586 }
587}
588
589//__________________________________________________________________________
591{
592 // fill for every sensor its tracking frame parameteres
593 if (!isTrackingFrameCached()) {
594 // special cache for sensors tracking frame X and alpha params
595 mCacheRefX.resize(mSize);
596 mCacheRefAlpha.resize(mSize);
597 for (int i = 0; i < mSize; i++) {
599 }
600 }
601}
602
603//__________________________________________________________________________
605{
606 int numberOfLayers = 0;
607
608 TGeoVolume* itsV = gGeoManager->GetVolume(getITSVolPattern());
609 if (itsV == nullptr) {
610 LOG(fatal) << getName() << " volume " << getITSVolPattern() << " is not in the geometry";
611 }
612
613 // Loop on all ITSV nodes, count Layer volumes by checking names
614 // Build on the fly layer - wrapper correspondence
615 TObjArray* nodes = itsV->GetNodes();
616 int nNodes = nodes->GetEntriesFast();
617 for (int j = 0; j < nNodes; j++) {
618 int lrID = -1;
619 auto nd = dynamic_cast<TGeoNode*>(nodes->At(j));
620 const char* name = nd->GetName();
621
622 if ((strstr(name, getITSLayerPattern()) != nullptr) || (strstr(name, getITS3LayerPattern()) != nullptr)) {
623 numberOfLayers++;
626 LOG(fatal) << "Failed to extract layer ID from the " << name;
627 }
628 mIsLayerITS3[lrID] = true;
629 }
630 mLayerToWrapper[lrID] = -1; // not wrapped
631 } else if (strstr(name, getITSWrapVolPattern()) != nullptr) { // this is a wrapper volume, may cointain layers
632 int wrID = -1;
634 LOG(fatal) << "Failed to extract wrapper ID from the " << name;
635 }
636 TObjArray* nodesW = nd->GetNodes();
637 int nNodesW = nodesW->GetEntriesFast();
638
639 for (int jw = 0; jw < nNodesW; jw++) {
640 auto ndW = dynamic_cast<TGeoNode*>(nodesW->At(jw))->GetName();
641 if ((strstr(ndW, getITSLayerPattern()) != nullptr) || (strstr(ndW, getITS3LayerPattern()) != nullptr)) {
642 if ((lrID = extractVolumeCopy(ndW, GeometryTGeo::getITSLayerPattern())) < 0) {
643 if ((lrID = extractVolumeCopy(ndW, GeometryTGeo::getITS3LayerPattern())) < 0) {
644 LOGP(fatal, "Failed to extract layer ID from wrapper volume '{}' from one of its nodes '{}'", name, ndW);
645 }
646 mIsLayerITS3[lrID] = true;
647 }
648 numberOfLayers++;
649 mLayerToWrapper[lrID] = wrID;
650 }
651 }
652 }
653 }
654 return numberOfLayers;
655}
656
657//__________________________________________________________________________
659{
660 // We take in account that we always have 2 and only 2 half barrels
661 int numberOfHalfBarrels = 2;
662
663 return numberOfHalfBarrels;
664}
665
666//__________________________________________________________________________
668{
669 int numberOfStaves = 0;
670 char hbarnam[30];
671 if (mNumberOfHalfBarrels == 0) {
672 snprintf(hbarnam, 30, "%s%d", mIsLayerITS3[lay] ? getITS3LayerPattern() : getITSLayerPattern(), lay);
673 } else {
674 snprintf(hbarnam, 30, "%s%d", mIsLayerITS3[lay] ? getITS3HalfBarrelPattern() : getITSHalfBarrelPattern(), lay);
675 }
676 TGeoVolume* volHb = gGeoManager->GetVolume(hbarnam);
677 if (volHb == nullptr) {
678 LOGP(fatal, "Can't find '{}' volume (ITS3={})", hbarnam, mIsLayerITS3[lay]);
679 return -1;
680 }
681
682 // Loop on all half barrel nodes, count Stave volumes by checking names
683 int nNodes = volHb->GetNodes()->GetEntries();
684 for (int j = 0; j < nNodes; j++) {
685 // LOG(info) << "L" << lay << " " << j << " of " << nNodes << " "
686 // << volHb->GetNodes()->At(j)->GetName() << " "
687 // << mIsLayerITS3[lay] ? getITS3StavePattern() : getITSStavePattern() << " -> " << numberOfStaves;
688 if (strstr(volHb->GetNodes()->At(j)->GetName(), mIsLayerITS3[lay] ? getITS3StavePattern() : getITSStavePattern()) != nullptr) {
689 numberOfStaves++;
690 }
691 }
692 return mNumberOfHalfBarrels > 0 ? (numberOfStaves * mNumberOfHalfBarrels) : numberOfStaves;
693}
694
695//__________________________________________________________________________
697{
698 if (sHalfStaveName.empty()) {
699 return 0; // for the setup w/o substave defined the stave and the substave is the same thing
700 }
701 int nSS = 0;
702 char stavnam[30];
703 snprintf(stavnam, 30, "%s%d", mIsLayerITS3[lay] ? getITS3StavePattern() : getITSStavePattern(), lay);
704 TGeoVolume* volLd = gGeoManager->GetVolume(stavnam);
705 if (volLd == nullptr) {
706 LOG(fatal) << "can't find volume " << stavnam;
707 }
708 // Loop on all stave nodes, count Chip volumes by checking names
709 int nNodes = volLd->GetNodes()->GetEntries();
710 for (int j = 0; j < nNodes; j++) {
711 if (strstr(volLd->GetNodes()->At(j)->GetName(), mIsLayerITS3[lay] ? getITS3HalfStavePattern() : getITSHalfStavePattern()) != nullptr) {
712 nSS++;
713 }
714 }
715 return nSS;
716}
717
718//__________________________________________________________________________
720{
721 if (sModuleName.empty()) {
722 return 0;
723 }
724
725 char stavnam[30];
726 TGeoVolume* volLd = nullptr;
727
728 if (!sHalfStaveName.empty()) {
729 snprintf(stavnam, 30, "%s%d", mIsLayerITS3[lay] ? getITS3HalfStavePattern() : getITSHalfStavePattern(), lay);
730 volLd = gGeoManager->GetVolume(stavnam);
731 }
732 if (!volLd) { // no substaves, check staves
733 snprintf(stavnam, 30, "%s%d", mIsLayerITS3[lay] ? getITS3StavePattern() : getITSStavePattern(), lay);
734 volLd = gGeoManager->GetVolume(stavnam);
735 }
736 if (!volLd) {
737 return 0;
738 }
739
740 int nMod = 0;
741
742 // Loop on all substave nodes, count module volumes by checking names
743 int nNodes = volLd->GetNodes()->GetEntries();
744
745 for (int j = 0; j < nNodes; j++) {
746 if (strstr(volLd->GetNodes()->At(j)->GetName(), mIsLayerITS3[lay] ? getITS3ModulePattern() : getITSModulePattern())) {
747 nMod++;
748 }
749 }
750 return nMod;
751}
752
753//__________________________________________________________________________
755{
756#ifdef ENABLE_UPGRADES
757 // FS: TODO
758 // For now we hardcode ITS3 number of chips is eq. to the number of tiles per RSU
759 // The test in the end does not work for ITS3.
760 if (mIsLayerITS3[lay]) {
763 }
764#endif
765 int numberOfChips = 0;
766 char stavnam[30];
767 TGeoVolume* volLd = nullptr;
768
769 if (!sModuleName.empty()) {
770 snprintf(stavnam, 30, "%s%d", getITSModulePattern(), lay);
771 volLd = gGeoManager->GetVolume(stavnam);
772 }
773 if (!volLd) { // no modules on this layer, check substaves
774 if (!sHalfStaveName.empty()) {
775 snprintf(stavnam, 30, "%s%d", getITSHalfStavePattern(), lay);
776 volLd = gGeoManager->GetVolume(stavnam);
777 }
778 }
779 if (!volLd) { // no substaves on this layer, check staves
780 snprintf(stavnam, 30, "%s%d", getITSStavePattern(), lay);
781 volLd = gGeoManager->GetVolume(stavnam);
782 }
783 if (!volLd) {
784 LOG(fatal) << "can't find volume containing chips on layer " << lay;
785 }
786
787 // Loop on all stave nodes, count Chip volumes by checking names
788 int nNodes = volLd->GetNodes()->GetEntries();
789
790 double xmin = 1e9, xmax = -1e9, zmin = 1e9, zmax = -1e9;
791 double lab[3], loc[3] = {0, 0, 0};
792 double dx = -1, dz = -1;
793
794 for (int j = 0; j < nNodes; j++) {
795 TGeoNodeMatrix* node = (TGeoNodeMatrix*)volLd->GetNodes()->At(j);
796 if (strstr(node->GetName(), getITSChipPattern()) == nullptr) {
797 continue;
798 }
799 node->LocalToMaster(loc, lab);
800 if (lab[0] > xmax) {
801 xmax = lab[0];
802 }
803 if (lab[0] < xmin) {
804 xmin = lab[0];
805 }
806 if (lab[2] > zmax) {
807 zmax = lab[2];
808 }
809 if (lab[2] < zmin) {
810 zmin = lab[2];
811 }
812
813 numberOfChips++;
814
815 if (dx < 0) {
816 TGeoShape* chShape = node->GetVolume()->GetShape();
817 TGeoBBox* bbox = dynamic_cast<TGeoBBox*>(chShape);
818 if (!bbox) {
819 LOG(fatal) << "Chip " << node->GetName() << " volume is of unprocessed shape " << chShape->IsA()->GetName();
820 } else {
821 dx = 2 * bbox->GetDX();
822 dz = 2 * bbox->GetDZ();
823 }
824 }
825 }
826
827 double spanX = xmax - xmin;
828 double spanZ = zmax - zmin;
829 nrow = TMath::Nint(spanX / dx + 1);
830 int ncol = TMath::Nint(spanZ / dz + 1);
831 if (nrow * ncol != numberOfChips) {
832 LOG(error) << "Inconsistency between Nchips=" << numberOfChips << " and Nrow*Ncol=" << nrow << "*" << ncol << "->"
833 << nrow * ncol << "\n"
834 << "Extracted chip dimensions (x,z): " << dx << " " << dz << " Module Span: " << spanX << " " << spanZ << "\n"
835 << "xmin=" << xmin << " xmax=" << xmax
836 << " zmin=" << zmin << " zmax=" << zmax;
837 }
838 return numberOfChips;
839}
840
841//__________________________________________________________________________
843{
844 char stavnam[30];
845 snprintf(stavnam, 30, "%s%d", mIsLayerITS3[lay] ? getITS3LayerPattern() : getITSLayerPattern(), lay);
846 TGeoVolume* volLd = gGeoManager->GetVolume(stavnam);
847 if (!volLd) {
848 LOG(fatal) << "can't find volume " << stavnam;
849 return -1;
850 }
851 return volLd->GetUniqueID();
852}
853
854//__________________________________________________________________________
855void GeometryTGeo::Print(Option_t*) const
856{
857 if (!isBuilt()) {
858 LOGF(info, "Geometry not built yet!");
859 return;
860 }
861
862 LOGF(info, "Summary of GeometryTGeo: %s", getName());
863 LOGF(info, "NLayers:%d NChips:%d\n", mNumberOfLayers, getNumberOfChips());
864 for (int i = 0; i < mNumberOfLayers; i++) {
865 LOGF(info,
866 "Lr%2d\tNStav:%2d\tNChips:%2d "
867 "(%dx%-2d)\tNMod:%d\tNSubSt:%d\tNSt:%3d\tChip#:%5d:%-5d\tWrapVol:%d",
872 }
873}
874
875//__________________________________________________________________________
876void GeometryTGeo::extractSensorXAlpha(int isn, float& x, float& alp)
877{
878 // calculate r and phi of the impact of the normal on the sensor
879 // (i.e. phi of the tracking frame alpha and X of the sensor in this frame)
880
881 const TGeoHMatrix* matL2G = extractMatrixSensor(isn);
882 double locA[3] = {-100., 0., 0.}, locB[3] = {100., 0., 0.}, gloA[3], gloB[3];
883 int iLayer = getLayer(isn);
884
885#ifdef ENABLE_UPGRADES
886 if (mIsLayerITS3[iLayer]) {
887 // We need to calcualte the line tangent at the mid-point in the geometry
888 const auto radius = o2::its3::constants::radii[iLayer];
889 const auto phi1 = o2::its3::constants::tile::width / radius;
890 const auto phi2 = o2::its3::constants::pixelarray::width / radius + phi1;
891 const auto phi3 = (phi2 - phi1) / 2.; // mid-point in phi
892 const auto x = radius * std::cos(phi3);
893 const auto y = radius * std::sin(phi3);
894 // For the tangent we make the parametric line equation y = m * x - c
895 const auto m = x / y;
896 const auto c = y - m * x;
897 // Now we can given any x calulate points along this line, we pick points far away,
898 // the calculation of the normal should work then below.
899 locA[1] = m * locA[0] + c;
900 locB[1] = m * locB[0] + c;
901 }
902#endif
903
904 matL2G->LocalToMaster(locA, gloA);
905 matL2G->LocalToMaster(locB, gloB);
906 double dx = gloB[0] - gloA[0], dy = gloB[1] - gloA[1];
907 double t = (gloB[0] * dx + gloB[1] * dy) / (dx * dx + dy * dy);
908 double xp = gloB[0] - dx * t, yp = gloB[1] - dy * t;
909 x = Sqrt(xp * xp + yp * yp);
910 alp = ATan2(yp, xp);
911 o2::math_utils::bringTo02Pi(alp);
912}
913
914//__________________________________________________________________________
915TGeoHMatrix& GeometryTGeo::createT2LMatrix(int isn)
916{
917 // create for sensor isn the TGeo matrix for Tracking to Local frame transformations
918 static TGeoHMatrix t2l;
919 float x = 0.f, alp = 0.f;
920 extractSensorXAlpha(isn, x, alp);
921 t2l.Clear();
922 t2l.RotateZ(alp * RadToDeg()); // rotate in direction of normal to the sensor plane
923 const TGeoHMatrix* matL2G = extractMatrixSensor(isn);
924 const TGeoHMatrix& matL2Gi = matL2G->Inverse();
925 t2l.MultiplyLeft(&matL2Gi);
926 return t2l;
927}
928
929//__________________________________________________________________________
930int GeometryTGeo::extractVolumeCopy(const char* name, const char* prefix) const
931{
932 TString nms = name;
933 if (!nms.BeginsWith(prefix)) {
934 return -1;
935 }
936 nms.Remove(0, strlen(prefix));
937 if (!isdigit(nms.Data()[0])) {
938 return -1;
939 }
940 return nms.Atoi();
941}
Definition of the GeometryManager class.
int32_t i
Definition of the GeometryTGeo class.
ClassImp(o2::its::GeometryTGeo)
uint32_t j
Definition RawData.h:0
uint32_t c
Definition RawData.h:2
Definition of the SegmentationAlpide class.
Definition of the SegmentationSuperAlpide class.
std::ostringstream debug
Static class with identifiers, bitmasks and names for ALICE detectors.
Definition DetID.h:58
static constexpr const char * getName(ID id)
names of defined detectors
Definition DetID.h:145
static constexpr ID ITS
Definition DetID.h:63
o2::detectors::DetID mDetID
detector ID
const MatrixCache< Mat3D > & getCacheT2L() const
const char * getName() const
o2::math_utils::Rotation2Df_t Rot2D
const Mat3D & getMatrixL2G(int sensID) const
const MatrixCache< Mat3D > & getCacheT2G() const
int mSize
prebooked number of sensors
const MatrixCache< Rot2D > & getCacheT2GRot() const
const MatrixCache< Mat3D > & getCacheL2G() const
Segmentation and response for pixels in ITS3 upgrade.
static constexpr float mSensorLayerThicknessEff
int extractNumberOfLayers()
Determines the number of layers in the Geometry.
TGeoHMatrix & createT2LMatrix(int isn)
static const char * getITS3ModulePattern()
std::vector< int > mNumberOfChipsPerHalfStave
number of chips per substave
o2::math_utils::Transform3D Mat3D
static const char * getITSLayerPattern()
static const std::string sLayerNameITS3
Layer name for ITS3.
static const char * composeSymNameLayer(int lr, bool isITS3=false)
sym name of the layer
static const std::string sStaveNameITS3
Stave name for ITS3.
int getChipIdInHalfStave(int index) const
Get chip number within stave, from 0.
static const std::string sSensorNameITS3
Sensor name for ITS3.
static const char * composeSymNameITS(bool isITS3=false)
sym name of the layer
std::vector< int > mNumberOfHalfStaves
the number of substaves/stave(layer)
static std::string sHalfBarrelName
HalfBarrel name.
static std::string sHalfStaveName
HalfStave name.
static const char * getITS3SegmentPattern(int layer)
static const char * getITS3ChipPattern()
static const char * getITS3TilePattern(int layer)
static const char * getITSSensorPattern()
bool getChipId(int index, int &lay, int &sta, int &ssta, int &mod, int &chip) const
int extractNumberOfChipsPerModule(int lay, int &nrow) const
static std::string sLayerName
Layer name.
int getHalfBarrel(int index) const
Get chip half barrel, from 0.
std::vector< int > mNumberOfStaves
number of staves/layer(layer)
static const char * getITSHalfBarrelPattern()
std::vector< int > mNumberOfModules
number of modules/substave(layer)
TGeoHMatrix * extractMatrixSensor(int index) const
static const char * getITS3RSUPattern(int layer)
int getLayer(int index) const
Get chip layer, from 0.
static const char * composeSymNameHalfBarrel(int lr, int hba, bool isITS3=false)
Sym name of the half barrel at given layer.
std::array< char, MAXLAYERS > mLayerToWrapper
Layer to wrapper correspondence.
std::array< bool, MAXLAYERS > mIsLayerITS3
flag with the information of the ITS version (ITS2 or ITS3)
static const char * getITS3HalfStavePattern()
float getSensorRefAlpha(int isn) const
static const std::string sModuleNameITS3
Module name for ITS3.
int getChipIdInStave(int index) const
Get chip number within stave, from 0.
static std::string sModuleName
Module name.
static const std::string sHalfStaveNameITS3
HalfStave name for ITS3.
TString getMatrixPath(int index) const
int extractNumberOfModules(int lay) const
static const char * composeSymNameHalfStave(int lr, int hba, int sta, int ssta, bool isITS3=false)
Sym name of the stave at given layer/halfbarrel.
~GeometryTGeo() override
Default destructor, don't use.
static const char * getITS3CarbonFormPattern(int layer)
int extractVolumeCopy(const char *name, const char *prefix) const
Extract number following the prefix in the name string.
const Mat3D getT2LMatrixITS3(int isn, float alpha)
static const char * composeSymNameChip(int lr, int hba, int sta, int ssta, int mod, int chip, bool isITS3=false)
Sym name of the chip in the given layer/halfbarrel/stave/substave/module.
static const char * getITS3PixelArrayPattern(int layer)
static const char * getITSChipPattern()
static const char * composeSymNameModule(int lr, int hba, int sta, int ssta, int mod, bool isITS3=false)
Sym name of the substave at given layer/halfbarrel/stave.
int extractLayerChipType(int lay) const
std::vector< float > mCacheRefX
sensors tracking plane reference X
std::vector< int > mNumberOfChipsPerModule
number of chips per module (group of chips on substaves)
static std::string sWrapperVolumeName
Wrapper volume name.
static const char * getITSVolPattern()
static const char * getITS3HalfBarrelPattern()
std::vector< int > mNumberOfChipsPerStave
number of chips per stave
bool isTrackingFrameCached() const
static const std::string sHalfBarrelNameITS3
HalfBarrel name for ITS3.
void Build(int loadTrans=0) override
Exract ITS parameters from TGeo.
void extractSensorXAlpha(int isn, float &x, float &alp)
std::vector< int > mNumberOfChipsPerLayer
number of chips per stave
int extractNumberOfStaves(int lay) const
int getHalfStave(int index) const
Get chip substave id in stave, from 0.
int getFirstChipIndex(int lay) const
static const char * getITSModulePattern()
int getChipIdInLayer(int index) const
Get chip number within layer, from 0.
static const std::string sChipNameITS3
Chip name for ITS3.
static std::string sStaveName
Stave name.
int extractNumberOfHalfStaves(int lay) const
Int_t mNumberOfHalfBarrels
number of halfbarrels
void fillMatrixCache(int mask) override
void Print(Option_t *opt="") const
static void adopt(GeometryTGeo *raw, bool canDelete=false)
int getChipIndex(int lay, int detInLay) const
std::vector< float > mCacheRefAlpha
sensors tracking plane reference alpha
Int_t mNumberOfLayers
number of layers
static const char * composeSymNameStave(int lr, int hba, int sta, bool isITS3=false)
Sym name of the stave at given layer.
int getStave(int index) const
Get chip stave, from 0.
static const char * getITS3LayerPattern()
int getModule(int index) const
Get chip module id in substave, from 0.
static const char * getITS3StavePattern()
static std::string sSensorName
Sensor name.
static std::string sChipName
Chip name.
std::vector< int > mNumberOfChipRowsPerModule
number of chips rows per module (relevant for OB modules)
int getChipIdInModule(int index) const
Get chip number within module, from 0.
std::vector< int > mLastChipIndex
max ID of the detctor in the layer
static const char * getITSHalfStavePattern()
int extractNumberOfHalfBarrels() const
std::vector< int > mNumberOfChipsPerHalfBarrel
number of chips per halfbarrel
static std::string sVolumeName
Mother volume name.
static const char * getITSStavePattern()
int getLastChipIndex(int lay) const
static const char * getITSWrapVolPattern()
Int_t getNumberOfChips() const
static constexpr float SensorLayerThickness
static constexpr float SensorLayerThicknessEff
transformation types
Definition Cartesian.h:62
GLdouble n
Definition glcorearb.h:1982
GLfloat GLfloat GLfloat alpha
Definition glcorearb.h:279
GLint GLenum GLint x
Definition glcorearb.h:403
const GLfloat * m
Definition glcorearb.h:4066
GLuint index
Definition glcorearb.h:781
GLuint const GLchar * name
Definition glcorearb.h:781
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLint y
Definition glcorearb.h:270
GLsizei const GLchar *const * path
Definition glcorearb.h:3591
GLboolean r
Definition glcorearb.h:1233
GLint GLuint mask
Definition glcorearb.h:291
constexpr unsigned int nTiles
Definition SpecsV2.h:75
constexpr float width
Definition SpecsV2.h:63
constexpr std::array< float, nLayers > radii
Definition SpecsV2.h:116
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
static constexpr int L2G
Definition Cartesian.h:54
static constexpr int T2L
Definition Cartesian.h:55
static constexpr int T2GRot
Definition Cartesian.h:57
static constexpr int T2G
Definition Cartesian.h:56
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"