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