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#include "TRKBase/Specs.h"
16#include <TMath.h>
17
18#include <limits>
19
21
22namespace o2
23{
24namespace trk
25{
26std::unique_ptr<o2::trk::GeometryTGeo> GeometryTGeo::sInstance;
27
28// Names
29std::string GeometryTGeo::sVolumeName = "TRKV";
30std::string GeometryTGeo::sServiceVolName = "TRKService";
31std::string GeometryTGeo::sLayerName = "TRKLayer";
32std::string GeometryTGeo::sPetalAssemblyName = "PETAL";
33std::string GeometryTGeo::sPetalName = "PETALCASE";
34std::string GeometryTGeo::sPetalDiskName = "DISK";
35std::string GeometryTGeo::sPetalLayerName = "LAYER";
36std::string GeometryTGeo::sStaveName = "TRKStave";
37std::string GeometryTGeo::sHalfStaveName = "TRKHalfStave";
38std::string GeometryTGeo::sModuleName = "TRKModule";
39std::string GeometryTGeo::sChipName = "TRKChip";
40std::string GeometryTGeo::sSensorName = "TRKSensor";
41std::string GeometryTGeo::sDeadzoneName = "TRKDeadzone";
42std::string GeometryTGeo::sMetalStackName = "TRKMetalStack";
43
44std::string GeometryTGeo::sWrapperVolumeName = "TRKUWrapVol";
45
46std::string GeometryTGeo::sFT3VolumeName = "FT3V";
47std::string GeometryTGeo::sFT3InnerVolumeName = "FT3Inner";
48std::string GeometryTGeo::sFT3LayerName = "FT3Layer";
49// TODO: chip and passive are only used by trapezoidal geom; use same for all?
50std::string GeometryTGeo::sFT3ChipName = "FT3Chip";
51std::string GeometryTGeo::sFT3PassiveName = "Passive";
52// TODO: this is now only used for the not-segmented version; synchronise?
53std::string GeometryTGeo::sFT3SensorName = "FT3Sensor";
54
56{
57 if (!mOwner) {
58 mOwner = true;
59 sInstance.release();
60 }
61}
62GeometryTGeo::GeometryTGeo(bool build, int loadTrans) : DetMatrixCache(detectors::DetID::TRK)
63{
64 if (sInstance) {
65 LOGP(fatal, "Invalid use of public constructor: o2::trk::GeometryTGeo instance exists");
66 }
67 mLayerToWrapper.fill(-1);
68 if (build) {
69 Build(loadTrans);
70 }
71}
72
73//__________________________________________________________________________
74void GeometryTGeo::Build(int loadTrans)
75{
80
81 if (isBuilt()) {
82 LOGP(warning, "Already built");
83 return; // already initialized
84 }
85
86 if (gGeoManager == nullptr) {
87 LOGP(fatal, "Geometry is not loaded");
88 }
89
91
92 LOG(debug) << "Overall layout ML and OT: " << mLayoutMLOT;
93
100
105
110
113 // mLastChipIndexMLOT.resize(mNumberOfLayersMLOT); /// ML and OT are part of TRK as the same detector, without disks
114
115 for (int i = 0; i < mNumberOfLayersMLOT; i++) {
117 mNumberOfStaves[i] = 1;
119 mNumberOfModules[i] = 1;
120 mNumberOfChips[i] = 1;
121 } else {
126 }
127 }
128
129 int numberOfChipsTotal = 0;
130
132 for (int i = 0; i < mNumberOfPetalsVD; i++) {
134 numberOfChipsTotal += mNumberOfChipsPerPetalVD[i];
135 mLastChipIndex[i] = numberOfChipsTotal - 1;
136 mLastChipIndexVD[i] = numberOfChipsTotal - 1;
137 }
138
140 for (int i = 0; i < mNumberOfLayersMLOT; i++) {
142 numberOfChipsTotal += mNumberOfChipsPerLayerMLOT[i];
143 mLastChipIndex[i + mNumberOfPetalsVD] = numberOfChipsTotal - 1;
144 }
145
146 // Forward discs (FT3) part
147 int totDiscs = 0;
148 int absStaveIdx = 0;
149
150 if (mFirstChipIndexStave.size() == 0) {
151 mFirstChipIndexStave.push_back(numberOfChipsTotal);
152 mFirstChipIndexMLOTDisc.push_back(numberOfChipsTotal);
153 }
154 if (mFirstStaveIndexDisc.size() == 0) {
155 mFirstStaveIndexDisc.push_back(0);
156 }
157 std::vector<int> numberOfDiscs;
158 for (int iDir = 0; iDir < 2; iDir++) {
159 numberOfDiscs.push_back(extractNumberOfDisksMLOT(iDir));
160 totDiscs += numberOfDiscs[iDir];
161 LOG(debug) << "direction " << iDir << "; disk total " << totDiscs;
162
163 for (int iDisc = 0; iDisc < numberOfDiscs[iDir]; iDisc++) {
164 TGeoVolume* trkV = gGeoManager->GetVolume(getTRKVolPattern());
165 if (trkV == nullptr) {
166 LOG(fatal) << getName() << " volume " << getTRKVolPattern() << " is not in the geometry";
167 }
168 auto layerNode = trkV->GetNode(Form("%s_1", composeSymNameLayerFT3(iDir, iDisc)));
169 if (layerNode == nullptr) {
170 LOG(info) << "Could not find layer node " << Form("%s_1", composeSymNameLayerFT3(iDir, iDisc));
171 continue;
172 }
173 auto layerVol = layerNode->GetVolume();
174 if (layerVol == nullptr) {
175 LOG(fatal) << "Could not find layer volume " << Form("%s_1", composeSymNameLayerFT3(iDir, iDisc));
176 }
177 TObjArray* nodes = layerVol->GetNodes();
178 int nNodes = nodes->GetEntriesFast();
179 int nStaves = 0;
180 int nSensor = 0;
181 std::vector<int> chipsPerStave;
182 for (int j = 0; j < nNodes; j++) {
183 auto nd = dynamic_cast<TGeoNode*>(nodes->At(j));
184 const char* name = nd->GetName();
185 if (strstr(name, "FT3Sensor") != nullptr && strstr(name, "Inactive") == nullptr) {
186 int direction = 0, layer = 0;
187 int stave = 0, chip = 0;
188 extractChipIdsFT3(name, layer, stave, chip);
189 if (stave >= chipsPerStave.size()) {
190 chipsPerStave.resize(stave + 1, 0);
191 nStaves = stave + 1;
192 }
193 // if (chip + 1 > mChipStaveIds.size()) mChipStaveIds.resize(chip+1);
194 if (chip + 1 >= chipsPerStave[stave]) {
195 chipsPerStave[stave] = chip + 1;
196 }
197 nSensor++;
198 }
199 }
200 LOG(debug) << "direction " << iDir << " disc " << iDisc << " has " << nNodes << " nodes of which " << nSensor << " sensors in " << chipsPerStave.size() << " staves";
201
202 if (nStaves != chipsPerStave.size()) {
203 LOG(info) << "Inconsistency in stave count " << nStaves << " " << chipsPerStave.size();
204 }
205 mFirstChipIndexStave.resize(absStaveIdx + chipsPerStave.size() + 1, -1);
206 for (int nChips : chipsPerStave) {
207 LOG(debug) << "Absolute Stave ID " << absStaveIdx << " : " << nChips << " sensors, setting first chip ID for next stave to " << mFirstChipIndexStave[absStaveIdx] + nChips;
208 numberOfChipsTotal += nChips;
209 mFirstChipIndexStave[absStaveIdx + 1] = mFirstChipIndexStave[absStaveIdx] + nChips;
210 absStaveIdx++;
211 }
212 mFirstStaveIndexDisc.push_back(absStaveIdx);
213 mFirstChipIndexMLOTDisc.push_back(numberOfChipsTotal);
214 LOG(debug) << "Total sensors so far " << numberOfChipsTotal;
215 }
216 }
217 setSize(numberOfChipsTotal);
218 if (numberOfChipsTotal > std::numeric_limits<unsigned short>::max()) {
219 LOG(fatal) << "Too many sensor chips in TRK: " << numberOfChipsTotal;
220 }
221 // TODO: add corresponding info for FT3
224 fillMatrixCache(loadTrans);
225 LOG(info) << "Build done";
226}
227
228//__________________________________________________________________________
230{
231 if (index >= 0 && index <= mLastChipIndexVD[mLastChipIndexVD.size() - 1]) {
232 return 0;
233 } else if (index <= mLastChipIndex[mLastChipIndex.size() - 1]) {
234 return 1;
235 } else if (index < mFirstChipIndexMLOTDisc[mFirstChipIndexMLOTDisc.size() - 1]) {
236 return 2;
237 }
238 return -1;
239}
240
241//__________________________________________________________________________
243{
244 int petalcase = 0;
245
246 int subDetID = getSubDetID(index);
247 if (subDetID == 1) {
248 return -1;
249 } else if (index <= mLastChipIndexVD[mNumberOfPetalsVD - 1]) {
250 while (index > mLastChipIndexVD[petalcase]) {
251 petalcase++;
252 }
253 }
254 return petalcase;
255}
256
257//__________________________________________________________________________
259{
260 int subDetID = getSubDetID(index);
261 int petalcase = getPetalCase(index);
262
263 if (subDetID == 0) {
265 return -1;
266 }
267 return (index % mNumberOfChipsPerPetalVD[petalcase]) - mNumberOfLayersVD;
268 }
269
270 return -1;
271}
272
273//__________________________________________________________________________
275{
276 int subDetID = getSubDetID(index);
277 int lay = 0;
278
279 if (subDetID == 0) {
280 int petalcase = getPetalCase(index);
282 return -1;
283 }
284 return index % mNumberOfChipsPerPetalVD[petalcase];
285 } else if (subDetID == 1) {
286 while (index > mLastChipIndex[lay]) {
287 lay++;
288 }
289 return lay - mNumberOfPetalsVD;
290 } else if (subDetID == 2) {
291 lay = mNumberOfDisksMLOT - 1;
292 while (index < mFirstChipIndexMLOTDisc[lay] && lay > 0) {
293 lay--;
294 }
295 return lay;
296 }
297 return -1;
298}
299//__________________________________________________________________________
301{
302 if (getDisk(index) != -1) {
303 return -1;
304 }
305 int subDetID = getSubDetID(index);
306 int firstDetLayer = 0;
307
308 // NOTE: taking these from o2::trk::constants, instead
309 // of the geometry that is constructed in the 'Build' function
310 // risks inconsistencies...
311
312 if (subDetID == 1) {
314 } else if (subDetID == 2) {
316 }
317 return firstDetLayer + getLayer(index);
318}
319//__________________________________________________________________________
321{
322 int subDetID = getSubDetID(index);
323 int lay = getLayer(index);
324 int petalcase = getPetalCase(index);
325
326 if (subDetID == 0) {
327 return -1;
328 } else if (subDetID == 1) {
329 int lay = getLayer(index);
330 index -= getFirstChipIndex(lay, petalcase, subDetID); // get the index of the sensing element in the layer
331
332 const int Nhs = mNumberOfHalfStaves[lay];
333 const int Nmod = mNumberOfModules[lay];
334 const int Nchip = mNumberOfChips[lay];
335
336 if (Nhs == 2) {
337 int chipsPerModule = Nchip;
338 int chipsPerHalfStave = Nmod * chipsPerModule;
339 int chipsPerStave = Nhs * chipsPerHalfStave;
340 return index / chipsPerStave;
341 } else if (Nhs == 1) {
342 int chipsPerModule = Nchip;
343 int chipsPerStave = Nmod * chipsPerModule;
344 return index / chipsPerStave;
345 }
346 } else if (subDetID == 2) { // Disks FT3
347 int lay = getLayer(index);
348 int absStave = mFirstStaveIndexDisc[lay];
349 while (index >= mFirstChipIndexStave[absStave] && absStave < mFirstStaveIndexDisc[lay + 1]) {
350 absStave++;
351 }
352 return absStave - 1 - mFirstStaveIndexDisc[lay];
353 }
354 return -1;
355}
356
357//__________________________________________________________________________
359{
360 int subDetID = getSubDetID(index);
361 int lay = getLayer(index);
362 int petalcase = getPetalCase(index);
363
364 if (subDetID == 0) {
365 return -1;
366 } else if (subDetID == 1) {
367 int lay = getLayer(index);
368 index -= getFirstChipIndex(lay, petalcase, subDetID); // get the index of the sensing element in the layer
369
370 const int Nhs = mNumberOfHalfStaves[lay];
371 const int Nmod = mNumberOfModules[lay];
372 const int Nchip = mNumberOfChips[lay];
373
374 int chipsPerModule = Nchip;
375 int chipsPerHalfStave = Nmod * chipsPerModule;
376 int chipsPerStave = Nhs * chipsPerHalfStave;
377
378 int rem = index % chipsPerStave;
379 return rem / chipsPerHalfStave; // 0 = left, 1 = right
380 }
381 return -1;
382}
383
384//__________________________________________________________________________
386{
387 int subDetID = getSubDetID(index);
388 int lay = getLayer(index);
389 int petalcase = getPetalCase(index);
390
391 if (subDetID == 0) {
392 return -1;
393 } else if (subDetID == 1) {
394 int lay = getLayer(index);
395 index -= getFirstChipIndex(lay, petalcase, subDetID); // get the index of the sensing element in the layer
396
397 const int Nhs = mNumberOfHalfStaves[lay];
398 const int Nmod = mNumberOfModules[lay];
399 const int Nchip = mNumberOfChips[lay];
400
401 if (Nhs == 2) {
402 int chipsPerModule = Nchip;
403 int chipsPerHalfStave = Nmod * chipsPerModule;
404 int rem = index % (Nhs * chipsPerHalfStave);
405 rem = rem % chipsPerHalfStave;
406 return rem / chipsPerModule;
407 } else if (Nhs == 1) {
408 int chipsPerModule = Nchip;
409 int rem = index % (Nmod * chipsPerModule);
410 return rem / chipsPerModule;
411 }
412 }
413 return -1;
414}
415
416//__________________________________________________________________________
418{
419 int subDetID = getSubDetID(index);
420 int lay = getLayer(index);
421 int petalcase = getPetalCase(index);
422
423 if (subDetID == 0) {
424 return -1;
425 } else if (subDetID == 1) {
426 int lay = getLayer(index);
427 index -= getFirstChipIndex(lay, petalcase, subDetID); // get the index of the sensing element in the layer
428
429 const int Nhs = mNumberOfHalfStaves[lay];
430 const int Nmod = mNumberOfModules[lay];
431 const int Nchip = mNumberOfChips[lay];
432
433 if (Nhs == 2) {
434 int chipsPerModule = Nchip;
435 return index % chipsPerModule;
436 } else if (Nhs == 1) {
437 int chipsPerModule = Nchip;
438 return index % chipsPerModule;
439 }
440 } else if (subDetID == 2) { // Forward disks (FT3)
441 int lay = getLayer(index);
442 int stave = getStave(index);
443 return index - mFirstChipIndexStave[mFirstStaveIndexDisc[lay] + stave];
444 }
445 return -1;
446}
447
448//__________________________________________________________________________
449unsigned short GeometryTGeo::getChipIndex(int subDetID, int petalcase, int disk, int lay, int stave, int halfstave, int mod, int chip) const
450{
451 if (subDetID == 0) { // VD
452 if (lay == -1) { // disk
453 return getFirstChipIndex(lay, petalcase, subDetID) + mNumberOfLayersVD + disk;
454 } else { // layer
455 return getFirstChipIndex(lay, petalcase, subDetID) + lay;
456 }
457 } else if (subDetID == 1) { // MLOT
458 const int Nhs = mNumberOfHalfStaves[lay]; // 1 or 2
459 const int Nmod = mNumberOfModules[lay]; // module per half-stave (per stave if Nhs==1)
460 const int Nchip = mNumberOfChips[lay]; // chips per module
461
462 if (Nhs == 2) { // staggered geometry: layer -> stave -> halfstave -> mod -> chip
463 int chipsPerModule = Nchip;
464 int chipsPerHalfStave = Nmod * chipsPerModule;
465 int chipsPerStave = Nhs * chipsPerHalfStave;
466 return getFirstChipIndex(lay, petalcase, subDetID) + stave * chipsPerStave + halfstave * chipsPerHalfStave + mod * chipsPerModule + chip;
467 } else if (Nhs == 1) { // turbo geometry: layer -> stave -> mod -> chip (no halfstave)
468 int chipsPerModule = Nchip;
469 int chipsPerStave = Nmod * chipsPerModule;
470 return getFirstChipIndex(lay, petalcase, subDetID) + stave * chipsPerStave + mod * chipsPerModule + chip;
471 }
472 }
473
474 LOGP(warning, "Chip index not found for subDetID {}, petalcase {}, disk {}, layer {}, stave {}, halfstave {}, module {}, chip {}, returning numeric limit", subDetID, petalcase, disk, lay, stave, halfstave, mod, chip);
475 return std::numeric_limits<unsigned short>::max(); // not found
476}
477
478//__________________________________________________________________________
479unsigned short GeometryTGeo::getChipIndex(int subDetID, int volume, int lay, int stave, int halfstave, int mod, int chip) const
480{
481 if (subDetID == 0) { // VD
482 return volume;
483
484 } else if (subDetID == 1) { // MLOT
485 const int Nhs = mNumberOfHalfStaves[lay]; // 1 or 2
486 const int Nmod = mNumberOfModules[lay]; // module per half-stave (per stave if Nhs==1)
487 const int Nchip = mNumberOfChips[lay]; // chips per module
488
489 if (Nhs == 2) { // staggered geometry: layer -> stave -> halfstave -> mod -> chip
490 int chipsPerModule = Nchip;
491 int chipsPerHalfStave = Nmod * chipsPerModule;
492 int chipsPerStave = Nhs * chipsPerHalfStave;
493 return getFirstChipIndex(lay, -1, subDetID) + stave * chipsPerStave + halfstave * chipsPerHalfStave + mod * chipsPerModule + chip;
494 } else if (Nhs == 1) { // turbo geometry: layer -> stave -> mod -> chip (no halfstave)
495 int chipsPerModule = Nchip;
496 int chipsPerStave = Nmod * chipsPerModule;
497 return getFirstChipIndex(lay, -1, subDetID) + stave * chipsPerStave + mod * chipsPerModule + chip;
498 }
499 } else if (subDetID == 2) { // FT3
500 if (lay < mFirstStaveIndexDisc.size() && mFirstStaveIndexDisc[lay] + stave < mFirstChipIndexStave.size()) {
501 return mFirstChipIndexStave[mFirstStaveIndexDisc[lay] + stave] + chip;
502 }
503 }
504 LOGP(warning, "Chip index not found for subDetID {}, volume {}, layer {}, stave {}, halfstave {}, module {}, chip {}, returning numeric limit", subDetID, volume, lay, stave, halfstave, mod, chip);
505 return std::numeric_limits<unsigned short>::max(); // not found
506}
507
508//__________________________________________________________________________
509bool GeometryTGeo::getChipID(int index, int& subDetID, int& petalcase, int& disk, int& lay, int& stave, int& halfstave, int& mod, int& chip) const
510{
511 subDetID = getSubDetID(index);
512 petalcase = getPetalCase(index);
513 disk = getDisk(index);
514 lay = getLayer(index);
515 stave = getStave(index);
516 if (mNumberOfHalfStaves[lay] == 2) {
517 halfstave = getHalfStave(index);
518 } else {
519 halfstave = 0; // if not staggered geometry, return 0
520 }
521 halfstave = getHalfStave(index);
522 mod = getModule(index);
523 chip = getChip(index);
524
525 return kTRUE;
526}
527
528//__________________________________________________________________________
530{
531
532 int subDetID, petalcase, disk, layer, stave, halfstave, mod, chip;
533 getChipID(index, subDetID, petalcase, disk, layer, stave, halfstave, mod, chip);
534
535 // PrintChipID(index, subDetID, petalcase, disk, layer, stave, halfstave, mod, chip);
536
537 TString path = Form("/cave_1/barrel_1/%s_2/", GeometryTGeo::getTRKVolPattern());
538
539 // build the path
540 if (subDetID == 0) { // VD
541 if (disk >= 0) {
542 path += Form("%s_%d_%d/", getTRKPetalAssemblyPattern(), petalcase, petalcase + 1); // PETAL_n
543 path += Form("%s%d_%s%d_1/", getTRKPetalPattern(), petalcase, getTRKPetalDiskPattern(), disk); // PETALCASEx_DISKy_1
544 path += Form("%s%d_%s%d_%s%d_1/", getTRKPetalPattern(), petalcase, getTRKPetalDiskPattern(), disk, getTRKChipPattern(), disk); // PETALCASEx_DISKy_TRKChipy_1
545 path += Form("%s%d_%s%d_%s%d_1/", getTRKPetalPattern(), petalcase, getTRKPetalDiskPattern(), disk, getTRKSensorPattern(), disk); // PETALCASEx_DISKy_TRKSensory_1
546 } else if (layer >= 0) {
547 path += Form("%s_%d_%d/", getTRKPetalAssemblyPattern(), petalcase, petalcase + 1); // PETAL_n
548 path += Form("%s%d_%s%d_1/", getTRKPetalPattern(), petalcase, getTRKPetalLayerPattern(), layer); // PETALCASEx_LAYERy_1
549 // path += Form("%s%d_%s%d_%s%d_1/", getTRKPetalPattern(), petalcase, getTRKPetalLayerPattern(), layer, getTRKStavePattern(), layer); // PETALCASEx_LAYERy_TRKStavey_1
550 path += Form("%s%d_%s%d_%s%d_1/", getTRKPetalPattern(), petalcase, getTRKPetalLayerPattern(), layer, getTRKChipPattern(), layer); // PETALCASEx_LAYERy_TRKChipy_1
551 path += Form("%s%d_%s%d_%s%d_1/", getTRKPetalPattern(), petalcase, getTRKPetalLayerPattern(), layer, getTRKSensorPattern(), layer); // PETALCASEx_LAYERy_TRKSensory_1
552 }
553 } else if (subDetID == 1) { // MLOT
554 path += Form("%s%d_1/", getTRKLayerPattern(), layer); // TRKLayerx_1
556 path += Form("%s%d_1/", getTRKSensorPattern(), layer); // TRKSensorx_1
557 } else {
558 path += Form("%s%d_%d/", getTRKStavePattern(), layer, stave); // TRKStavex_y
559 if (mNumberOfHalfStaves[layer] == 2) { // staggered geometry
560 path += Form("%s%d_%d/", getTRKHalfStavePattern(), layer, halfstave); // TRKHalfStavex_y
561 }
562 path += Form("%s%d_%d/", getTRKModulePattern(), layer, mod); // TRKModulx_y
563 path += Form("%s%d_%d/", getTRKChipPattern(), layer, chip); // TRKChipx_y
564 path += Form("%s%d_1/", getTRKSensorPattern(), layer); // TRKSensorx_1
565 }
566 } else if (subDetID == 2) {
567 int direction = 0;
568 if (layer >= mNumberOfDisksMLOT / 2) {
569 direction = 1;
571 }
572 path += Form("%s%d_%d_1/", getFT3LayerPattern(), direction, layer);
573 path += Form("FT3Sensor_Active_%d_%d_%d_%d_%d", direction, layer, stave, chip, chip);
574 }
575 return path;
576}
577
578//__________________________________________________________________________
580{
581 // extract matrix transforming from the PHYSICAL sensor frame to global one
582 // Note, the if the effective sensitive layer thickness is smaller than the
583 // total physical sensor tickness, this matrix is biased and connot be used
584 // directly for transformation from sensor frame to global one.
585 // Therefore we need to add a shift
586
587 auto path = getMatrixPath(index);
588
589 static TGeoHMatrix matTmp;
590 gGeoManager->PushPath(); // Preserve the modeler state.
591
592 if (!gGeoManager->cd(path.Data())) {
593 gGeoManager->PopPath();
594 LOG(error) << "Error in cd-ing to " << path.Data();
595 return nullptr;
596 } // end if !gGeoManager
597
598 matTmp = *gGeoManager->GetCurrentMatrix(); // matrix may change after cd
599
600 // RSS
601 // matTmp.Print();
602 // Restore the modeler state.
603 gGeoManager->PopPath();
604
605 static int chipInGlo{0};
606
608 // account for the difference between physical sensitive layer (where charge collection is simulated) and effective sensor thicknesses
609 // in the VD case this will be accounted by specialized functions during the clusterization (following what it is done for ITS3)
610 // this can be done once the right sensor thickness is in place in the geometry
611 // double delta = 0.;
612 // if (getSubDetID(index) == 1){ /// ML/OT
613 // delta = Segmentation::SensorLayerThicknessVD - Segmentation::SiliconTickness;
614 // static TGeoTranslation tra(0., 0.5 * delta, 0.);
615 // matTmp *= tra;
616 // }
617 // std::cout<<"-----"<<std::endl;
618 // matTmp.Print();
619
620 return &matTmp;
621}
622
623//__________________________________________________________________________
625{
626 for (int i = 0; i < mSize; i++) {
627 if (getSubDetID(i) == 1) {
628 sensorsMLOT.push_back(i); // TODO: this is now a trivial array where each element is a sequence number (expect that the first elements are skipped)
629 }
630 }
631}
632
633//__________________________________________________________________________
635{
636 // fill for every sensor of ML & OT its tracking frame parameters
637 int nSensMLOT = sensorsMLOT.size();
639 if (!isTrackingFrameCachedMLOT() && !sensorsMLOT.empty()) {
640 size_t newSize = nSensMLOT + nSensMLOTDisk;
641 mCacheRefXMLOT.resize(newSize);
642 mCacheRefAlphaMLOT.resize(newSize);
643 for (int i = 0; i < nSensMLOT; i++) {
644 int sensorId = sensorsMLOT[i];
646 }
647 for (int i = nSensMLOT; i < newSize; i++) {
648 // LOG(info) << "Getting XAlpha for disk chip " << mFirstChipIndexMLOTDisc[0] + i;
650 }
651 }
652}
653
654//__________________________________________________________________________
656{
657 if (mSize < 1) {
658 LOG(warning) << "The method Build was not called yet";
659 Build(mask);
660 return;
661 }
662
663 // build matrices
664 if ((mask & o2::math_utils::bit2Mask(o2::math_utils::TransformType::L2G)) && !getCacheL2G().isFilled()) {
665 // Matrices for Local (Sensor!!! rather than the full chip) to Global frame transformation
666 LOGP(info, "Loading {} L2G matrices from TGeo; there are {} matrices", getName(), mSize);
667 auto& cacheL2G = getCacheL2G();
668 cacheL2G.setSize(mSize);
669
670 for (int i = 0; i < mSize; i++) {
671 TGeoHMatrix* hm = extractMatrixSensor(i);
672 cacheL2G.setMatrix(Mat3D(*hm), i);
673 }
674 }
675
676 // build T2L matrices for ML & OT !! VD is yet to be implemented once its geometry will be more refined
677 if ((mask & o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L)) && !getCacheT2L().isFilled()) {
678 LOGP(info, "Loading {} T2L matrices from TGeo for ML & OT", getName());
679 if (sensorsMLOT.size()) {
680 int m_Size = sensorsMLOT.size();
681 auto& cacheT2L = getCacheT2L();
682 cacheT2L.setSize(m_Size);
683 for (int i = 0; i < m_Size; i++) {
684 int sensorID = sensorsMLOT[i];
685 TGeoHMatrix& hm = createT2LMatrixMLOT(sensorID);
686 cacheT2L.setMatrix(Mat3D(hm), i); // here, sensorIDs from 0 to 374, sensorIDs shifted to 36 !
687 }
688 }
689 }
690
691 // TODO: build matrices for the cases T2L, T2G and T2GRot when needed
692}
693
694//__________________________________________________________________________
695
696#ifdef ENABLE_UPGRADES
697const char* GeometryTGeo::composeSymNameLayer(int d, int layer)
698{
699 return Form("%s/%s%d", composeSymNameTRK(d), getTRKLayerPattern(), layer);
700}
701
702#endif
703
705{
706 return Form("%s%d_%d", GeometryTGeo::getFT3LayerPattern(), dir, layer);
707}
708
710{
711 return Form("%s/%s%d", composeSymNameLayer(d, layer), getTRKStavePattern(), layer);
712}
713
715{
716 return Form("%s/%s%d", composeSymNameStave(d, layer), getTRKModulePattern(), layer);
717}
718
720{
721 return Form("%s/%s%d", composeSymNameStave(d, layer), getTRKChipPattern(), layer);
722}
723
725{
726 return Form("%s/%s%d", composeSymNameChip(d, layer), getTRKSensorPattern(), layer);
727}
728
729//__________________________________________________________________________
730void GeometryTGeo::extractChipIdsFT3(std::string const volName, int& layer, int& stave, int& chip) const
731{
732 if (volName.find("FT3Sensor_Active") == 0) {
733 int idx = volName.find('_') + 1;
734 idx = volName.find('_', idx) + 1;
735 int direction = std::stoi(volName.substr(idx));
736 idx = volName.find('_', idx) + 1;
737 layer = std::stoi(volName.substr(idx));
738 idx = volName.find('_', idx) + 1;
739 stave = std::stoi(volName.substr(idx));
740 idx = volName.find('_', idx) + 1;
741 chip = std::stoi(volName.substr(idx));
742 if (direction == 1) {
744 }
745 } else {
746 LOG(error) << "extractChipIdsFT3: Not a sensor volume " << volName;
747 layer = -1;
748 }
749}
750
751//__________________________________________________________________________
753{
754 int numDiscs = 0;
755 while (gGeoManager->GetVolume(composeSymNameLayerFT3(dir, numDiscs))) {
756 numDiscs++;
757 } // Check maybe subvolume?
758 return numDiscs; // Assume same # layers on both sides
759}
760
761//__________________________________________________________________________
762int GeometryTGeo::extractVolumeCopy(const char* name, const char* prefix) const
763{
764 TString nms = name;
765 if (!nms.BeginsWith(prefix)) {
766 return -1;
767 }
768 nms.Remove(0, strlen(prefix));
769 if (!isdigit(nms.Data()[0])) {
770 return -1;
771 }
772 return nms.Atoi();
773}
774
775//__________________________________________________________________________
777{
778 int numberOfLayers = 0;
779 TGeoVolume* trkV = gGeoManager->GetVolume(getTRKVolPattern());
780 if (trkV == nullptr) {
781 LOG(fatal) << getName() << " volume " << getTRKVolPattern() << " is not in the geometry";
782 }
783
784 // Loop on all TRKV nodes, count Layer volumes by checking names
785 // Build on the fly layer - wrapper correspondence
786 TObjArray* nodes = trkV->GetNodes();
787 // nodes->Print();
788 int nNodes = nodes->GetEntriesFast();
789 for (int j = 0; j < nNodes; j++) {
790 int lrID = -1;
791 auto nd = dynamic_cast<TGeoNode*>(nodes->At(j));
792 const char* name = nd->GetName();
793 if (strstr(name, getTRKLayerPattern()) != nullptr) {
794 numberOfLayers++;
796 LOG(fatal) << "Failed to extract layer ID from the " << name;
797 }
798 mLayerToWrapper[lrID] = -1; // not wrapped
799 } else if (strstr(name, getTRKWrapVolPattern()) != nullptr) { // this is a wrapper volume, may cointain layers
800 int wrID = -1;
802 LOG(fatal) << "Failed to extract wrapper ID from the " << name;
803 }
804 TObjArray* nodesW = nd->GetNodes();
805 int nNodesW = nodesW->GetEntriesFast();
806
807 for (int jw = 0; jw < nNodesW; jw++) {
808 auto ndW = dynamic_cast<TGeoNode*>(nodesW->At(jw))->GetName();
809 if (strstr(ndW, getTRKLayerPattern()) != nullptr) {
810 if ((lrID = extractVolumeCopy(ndW, GeometryTGeo::getTRKLayerPattern())) < 0) {
811 LOGP(fatal, "Failed to extract layer ID from wrapper volume '{}' from one of its nodes '{}'", name, ndW);
812 }
813 numberOfLayers++;
814 mLayerToWrapper[lrID] = wrID;
815 }
816 }
817 }
818 }
819 return numberOfLayers;
820}
821
822//__________________________________________________________________________
824{
825 int numberOfPetals = 0;
826 TGeoVolume* trkV = gGeoManager->GetVolume(getTRKVolPattern());
827 if (!trkV) {
828 LOGP(fatal, "{} volume {} is not in the geometry", getName(), getTRKVolPattern());
829 return 0;
830 }
831
832 // Loop on all TRKV nodes, count PETAL assemblies and their contents
833 TObjArray* nodes = trkV->GetNodes();
834 if (!nodes) {
835 LOGP(warning, "{} volume has no child nodes", getTRKVolPattern());
836 return 0;
837 }
838
839 LOGP(info, "Searching for petal assemblies in {} (pattern: {})",
841
842 for (int j = 0; j < nodes->GetEntriesFast(); j++) {
843 auto* nd = dynamic_cast<TGeoNode*>(nodes->At(j));
844 const char* name = nd->GetName();
845
846 if (strstr(name, getTRKPetalAssemblyPattern()) != nullptr) {
847 numberOfPetals++;
848 LOGP(info, "Found petal assembly: {}", name);
849
850 // Get petal volume and its nodes for debugging
851 TGeoVolume* petalVol = nd->GetVolume();
852 if (petalVol) {
853 TObjArray* petalNodes = petalVol->GetNodes();
854 if (petalNodes) {
855 LOGP(debug, "Petal {} contains {} child nodes", name, petalNodes->GetEntriesFast());
856 // Print all nodes in this petal
857 for (int k = 0; k < petalNodes->GetEntriesFast(); k++) {
858 auto* petalNode = dynamic_cast<TGeoNode*>(petalNodes->At(k));
859 LOGP(debug, " Node {}: {}", k, petalNode->GetName());
860 }
861 } else {
862 LOGP(warning, "Petal {} has no child nodes", name);
863 }
864 } else {
865 LOGP(warning, "Petal {} has no volume", name);
866 }
867 }
868 }
869
870 if (numberOfPetals == 0) {
871 LOGP(warning, "No petal assemblies found in geometry");
872 } else {
873 LOGP(info, "Found {} petal assemblies", numberOfPetals);
874 }
875
876 return numberOfPetals;
877}
878
879//__________________________________________________________________________
881{
882 // The number of active parts returned here is 36 = 4 petals * (3 layers + 6 disks)
883 int numberOfParts = 0;
884 TGeoVolume* vdV = gGeoManager->GetVolume(getTRKVolPattern());
885 if (!vdV) {
886 LOGP(fatal, "{} volume {} is not in the geometry", getName(), getTRKVolPattern());
887 return 0;
888 }
889
890 // Find first petal to count its active parts
891 TObjArray* nodes = vdV->GetNodes();
892 if (!nodes) {
893 LOGP(warning, "{} volume has no child nodes", getTRKVolPattern());
894 return 0;
895 }
896
897 bool petalFound = false;
898
899 for (int j = 0; j < nodes->GetEntriesFast(); j++) {
900 auto* nd = dynamic_cast<TGeoNode*>(nodes->At(j));
901 const char* name = nd->GetName();
902 if (strstr(name, getTRKPetalAssemblyPattern()) == nullptr) {
903 continue;
904 }
905
906 petalFound = true;
907 LOGP(info, "Counting active parts in petal: {}", name);
908
909 // Found a petal, count its layers and disks
910 TGeoVolume* petalVol = nd->GetVolume();
911 if (!petalVol) {
912 LOGP(warning, "Petal {} has no volume", name);
913 break;
914 }
915
916 TObjArray* petalNodes = petalVol->GetNodes();
917 if (!petalNodes) {
918 LOGP(warning, "Petal {} has no child nodes", name);
919 break;
920 }
921
922 for (int k = 0; k < petalNodes->GetEntriesFast(); k++) {
923 auto* petalNode = dynamic_cast<TGeoNode*>(petalNodes->At(k));
924 const char* nodeName = petalNode->GetName();
925
926 if (strstr(nodeName, getTRKPetalLayerPattern()) != nullptr ||
927 strstr(nodeName, getTRKPetalDiskPattern()) != nullptr) {
928 numberOfParts++;
929 LOGP(debug, "Found active part in {}: {}", name, nodeName);
930 }
931 }
932 // We only need to check one petal as they're identical
933 break;
934 }
935
936 if (!petalFound) {
937 LOGP(warning, "No petal assembly found matching pattern '{}'", getTRKPetalAssemblyPattern());
938 return 0;
939 }
940
941 if (numberOfParts == 0) {
942 LOGP(warning, "No active parts (layers/disks) found in petal");
943 return 0;
944 }
945
946 // Multiply by number of petals since all petals are identical
947 int totalParts = numberOfParts * mNumberOfPetalsVD;
948 LOGP(info, "Total number of active parts: {} ({}*{})",
949 totalParts, numberOfParts, mNumberOfPetalsVD);
950 return totalParts;
951}
952
953//__________________________________________________________________________
955{
956 // Count disks in the first petal (all petals are identical)
957 int numberOfDisks = 0;
958 TGeoVolume* vdV = gGeoManager->GetVolume(getTRKVolPattern());
959 if (!vdV) {
960 LOGP(fatal, "{} volume {} is not in the geometry", getName(), getTRKVolPattern());
961 return 0;
962 }
963
964 // Find first petal
965 TObjArray* nodes = vdV->GetNodes();
966 if (!nodes) {
967 LOGP(warning, "{} volume has no child nodes", getTRKVolPattern());
968 return 0;
969 }
970
971 bool petalFound = false;
972
973 for (int j = 0; j < nodes->GetEntriesFast(); j++) {
974 auto* nd = dynamic_cast<TGeoNode*>(nodes->At(j));
975 if (strstr(nd->GetName(), getTRKPetalAssemblyPattern()) == nullptr) {
976 continue;
977 }
978
979 petalFound = true;
980 LOGP(info, "Counting disks in petal: {}", nd->GetName());
981
982 // Count disks in this petal
983 TGeoVolume* petalVol = nd->GetVolume();
984 if (!petalVol) {
985 LOGP(warning, "Petal {} has no volume", nd->GetName());
986 break;
987 }
988
989 TObjArray* petalNodes = petalVol->GetNodes();
990 if (!petalNodes) {
991 LOGP(warning, "Petal {} has no child nodes", nd->GetName());
992 break;
993 }
994
995 for (int k = 0; k < petalNodes->GetEntriesFast(); k++) {
996 auto* petalNode = dynamic_cast<TGeoNode*>(petalNodes->At(k));
997 if (strstr(petalNode->GetName(), getTRKPetalDiskPattern()) != nullptr) {
998 numberOfDisks++;
999 LOGP(info, "Found disk in {} : {}", nd->GetName(), petalNode->GetName());
1000 }
1001 }
1002 // One petal is enough
1003 break;
1004 }
1005
1006 if (!petalFound) {
1007 LOGP(warning, "No petal assembly found matching pattern '{}'", getTRKPetalAssemblyPattern());
1008 }
1009
1010 if (numberOfDisks == 0) {
1011 LOGP(warning, "No disks found in VD geometry");
1012 }
1013
1014 return numberOfDisks;
1015}
1016
1017//__________________________________________________________________________
1019{
1020 // Count layers in the first petal (all petals are identical)
1021 int numberOfLayers = 0;
1022 TGeoVolume* vdV = gGeoManager->GetVolume(getTRKVolPattern());
1023 if (!vdV) {
1024 LOGP(fatal, "{} volume {} is not in the geometry", getName(), getTRKVolPattern());
1025 return 0;
1026 }
1027
1028 // Find first petal
1029 TObjArray* nodes = vdV->GetNodes();
1030 if (!nodes) {
1031 LOGP(warning, "{} volume has no child nodes", getTRKVolPattern());
1032 return 0;
1033 }
1034
1035 bool petalFound = false;
1036
1037 for (int j = 0; j < nodes->GetEntriesFast(); j++) {
1038 auto* nd = dynamic_cast<TGeoNode*>(nodes->At(j));
1039 if (strstr(nd->GetName(), getTRKPetalAssemblyPattern()) == nullptr) {
1040 continue;
1041 }
1042
1043 petalFound = true;
1044 LOGP(info, "Counting layers in petal: {}", nd->GetName());
1045
1046 // Count layers in this petal
1047 TGeoVolume* petalVol = nd->GetVolume();
1048 if (!petalVol) {
1049 LOGP(warning, "Petal {} has no volume", nd->GetName());
1050 break;
1051 }
1052
1053 TObjArray* petalNodes = petalVol->GetNodes();
1054 if (!petalNodes) {
1055 LOGP(warning, "Petal {} has no child nodes", nd->GetName());
1056 break;
1057 }
1058
1059 for (int k = 0; k < petalNodes->GetEntriesFast(); k++) {
1060 auto* petalNode = dynamic_cast<TGeoNode*>(petalNodes->At(k));
1061 if (strstr(petalNode->GetName(), getTRKPetalLayerPattern()) != nullptr) {
1062 numberOfLayers++;
1063 LOGP(info, "Found layer in {} : {}", nd->GetName(), petalNode->GetName());
1064 }
1065 }
1066 // One petal is enough
1067 break;
1068 }
1069
1070 if (!petalFound) {
1071 LOGP(warning, "No petal assembly found matching pattern '{}'", getTRKPetalAssemblyPattern());
1072 }
1073
1074 if (numberOfLayers == 0) {
1075 LOGP(warning, "No layers found in VD geometry");
1076 }
1077
1078 return numberOfLayers;
1079}
1080
1081//__________________________________________________________________________
1083{
1084 // The number of chips per petal returned here is 9 for each layer = number of layers + number of quarters of disks per petal
1085 int numberOfChips = 0;
1086 TGeoVolume* vdV = gGeoManager->GetVolume(getTRKVolPattern());
1087 if (!vdV) {
1088 LOGP(fatal, "{} volume {} is not in the geometry", getName(), getTRKVolPattern());
1089 return 0;
1090 }
1091
1092 // Find first petal assembly
1093 TObjArray* nodes = vdV->GetNodes();
1094 if (!nodes) {
1095 LOGP(warning, "{} volume has no child nodes", getTRKVolPattern());
1096 return 0;
1097 }
1098
1099 bool petalFound = false;
1100
1101 for (int j = 0; j < nodes->GetEntriesFast(); j++) {
1102 auto* nd = dynamic_cast<TGeoNode*>(nodes->At(j));
1103 const char* name = nd->GetName();
1104 if (strstr(name, getTRKPetalAssemblyPattern()) == nullptr) {
1105 continue;
1106 }
1107
1108 petalFound = true;
1109 LOGP(info, "Counting chips in petal: {}", name);
1110
1111 // Found a petal, count sensors in its layers and disks
1112 TGeoVolume* petalVol = nd->GetVolume();
1113 if (!petalVol) {
1114 LOGP(warning, "Petal {} has no volume", name);
1115 break;
1116 }
1117
1118 TObjArray* petalNodes = petalVol->GetNodes();
1119 if (!petalNodes) {
1120 LOGP(warning, "Petal {} has no child nodes", name);
1121 break;
1122 }
1123
1124 for (int k = 0; k < petalNodes->GetEntriesFast(); k++) {
1125 auto* petalNode = dynamic_cast<TGeoNode*>(petalNodes->At(k));
1126 const char* nodeName = petalNode->GetName();
1127 TGeoVolume* vol = petalNode->GetVolume();
1128
1129 if (!vol) {
1130 LOGP(debug, "Node {} has no volume", nodeName);
1131 continue;
1132 }
1133
1134 // Look for sensors in this volume
1135 TObjArray* subNodes = vol->GetNodes();
1136 if (!subNodes) {
1137 LOGP(debug, "Node {} has no sub-nodes", nodeName);
1138 continue;
1139 }
1140
1141 for (int i = 0; i < subNodes->GetEntriesFast(); i++) {
1142 auto* subNode = dynamic_cast<TGeoNode*>(subNodes->At(i));
1143 if (strstr(subNode->GetName(), getTRKChipPattern()) != nullptr) {
1144 numberOfChips++;
1145 LOGP(debug, "Found chip in {}: {}", nodeName, subNode->GetName());
1146 }
1147 }
1148 }
1149 // We only need one petal
1150 break;
1151 }
1152
1153 if (!petalFound) {
1154 LOGP(warning, "No petal assembly found matching pattern '{}'", getTRKPetalAssemblyPattern());
1155 }
1156
1157 if (numberOfChips == 0) {
1158 LOGP(warning, "No chips/sensors found in VD petal");
1159 }
1160
1161 LOGP(info, "Number of chips per petal: {}", numberOfChips);
1162 return numberOfChips;
1163}
1164
1165//__________________________________________________________________________
1167{
1168 int numberOfStaves = 0;
1169
1170 std::string layName = Form("%s%d", getTRKLayerPattern(), lay);
1171 TGeoVolume* layV = gGeoManager->GetVolume(layName.c_str());
1172
1173 if (layV == nullptr) {
1174 LOG(fatal) << getName() << " volume " << getTRKLayerPattern() << " is not in the geometry";
1175 }
1176
1177 // Loop on all layV nodes, count Layer volumes by checking names
1178 TObjArray* nodes = layV->GetNodes();
1179 // std::cout << "Printing nodes for layer " << lay << std::endl;
1180 // nodes->Print();
1181 int nNodes = nodes->GetEntriesFast();
1182
1183 for (int j = 0; j < nNodes; j++) {
1184 int lrID = -1;
1185 auto nd = dynamic_cast<TGeoNode*>(nodes->At(j));
1186 const char* name = nd->GetName();
1187 if (strstr(name, getTRKStavePattern()) != nullptr) {
1188 numberOfStaves++;
1189 }
1190 }
1191 return numberOfStaves;
1192}
1193
1194//__________________________________________________________________________
1196{
1197 int numberOfHalfStaves = 0;
1198
1199 std::string staveName = Form("%s%d", getTRKStavePattern(), lay);
1200 TGeoVolume* staveV = gGeoManager->GetVolume(staveName.c_str());
1201
1202 if (staveV == nullptr) {
1203 LOG(fatal) << getName() << " volume " << getTRKStavePattern() << " is not in the geometry";
1204 }
1205
1206 // Loop on all layV nodes, count Layer volumes by checking names
1207 TObjArray* nodes = staveV->GetNodes();
1208 // std::cout << "Printing nodes for layer " << lay << std::endl;
1209 // nodes->Print();
1210 int nNodes = nodes->GetEntriesFast();
1211
1212 for (int j = 0; j < nNodes; j++) {
1213 auto nd = dynamic_cast<TGeoNode*>(nodes->At(j));
1214 const char* name = nd->GetName();
1215 if (strstr(name, getTRKHalfStavePattern()) != nullptr) {
1216 numberOfHalfStaves++;
1217 }
1218 }
1219
1220 if (numberOfHalfStaves == 0) {
1221 numberOfHalfStaves = 1;
1222 }
1223 return numberOfHalfStaves;
1224}
1225
1226//__________________________________________________________________________
1228{
1229 int numberOfModules = 0;
1230
1231 std::string staveName = Form("%s%d", (mNumberOfHalfStaves[lay] == 2 ? getTRKHalfStavePattern() : getTRKStavePattern()), lay);
1232 TGeoVolume* staveV = gGeoManager->GetVolume(staveName.c_str());
1233
1234 if (staveV == nullptr) {
1235 LOG(fatal) << getName() << " volume " << (mNumberOfHalfStaves[lay] == 2 ? getTRKHalfStavePattern() : getTRKStavePattern()) << " is not in the geometry";
1236 }
1237
1238 // Loop on all staveV nodes, count Module volumes by checking names
1239 TObjArray* nodes = staveV->GetNodes();
1240 int nNodes = nodes->GetEntriesFast();
1241
1242 for (int j = 0; j < nNodes; j++) {
1243 auto nd = dynamic_cast<TGeoNode*>(nodes->At(j));
1244 const char* name = nd->GetName();
1245 if (strstr(name, getTRKModulePattern()) != nullptr) {
1246 numberOfModules++;
1247 }
1248 }
1249 return numberOfModules;
1250}
1251
1252//__________________________________________________________________________
1254{
1255 int numberOfChips = 0;
1256
1257 std::string moduleName = Form("%s%d", getTRKModulePattern(), lay);
1258 TGeoVolume* moduleV = gGeoManager->GetVolume(moduleName.c_str());
1259
1260 if (moduleV == nullptr) {
1261 LOG(fatal) << getName() << " volume " << getTRKModulePattern() << " is not in the geometry";
1262 }
1263
1264 // Loop on all moduleV nodes, count Chip volumes by checking names
1265 TObjArray* nodes = moduleV->GetNodes();
1266 int nNodes = nodes->GetEntriesFast();
1267
1268 for (int j = 0; j < nNodes; j++) {
1269 auto nd = dynamic_cast<TGeoNode*>(nodes->At(j));
1270 const char* name = nd->GetName();
1271 if (strstr(name, getTRKChipPattern()) != nullptr) {
1272 numberOfChips++;
1273 }
1274 }
1275 return numberOfChips;
1276}
1277
1278//__________________________________________________________________________
1279void GeometryTGeo::PrintChipID(int index, int subDetID, int petalcase, int disk, int lay, int stave, int halfstave, int mod, int chip) const
1280{
1281 std::cout << "\nindex = " << index << std::endl;
1282 std::cout << "subDetID = " << subDetID << std::endl;
1283 std::cout << "petalcase = " << petalcase << std::endl;
1284 std::cout << "layer = " << lay << std::endl;
1285 std::cout << "disk = " << disk << std::endl;
1286 std::cout << "first chip index = " << getFirstChipIndex(lay, petalcase, subDetID) << std::endl;
1287 std::cout << "stave = " << stave << std::endl;
1288 std::cout << "halfstave = " << halfstave << std::endl;
1289 std::cout << "module = " << mod << std::endl;
1290 std::cout << "chip = " << chip << std::endl;
1291}
1292
1293//__________________________________________________________________________
1294void GeometryTGeo::Print(Option_t*) const
1295{
1296 if (!isBuilt()) {
1297 LOGF(info, "Geometry not built yet!");
1298 return;
1299 }
1300 std::cout << "Detector ID: " << sInstance.get()->getDetID() << std::endl;
1301
1302 LOGF(info, "Summary of GeometryTGeo: %s", getName());
1303 LOGF(info, "Number of layers ML + OT: %d", mNumberOfLayersMLOT);
1304 LOGF(info, "Number of active parts VD: %d", mNumberOfActivePartsVD);
1305 LOGF(info, "Number of layers VD: %d", mNumberOfLayersVD);
1306 LOGF(info, "Number of petals VD: %d", mNumberOfPetalsVD);
1307 LOGF(info, "Number of disks VD: %d", mNumberOfDisksVD);
1308 LOGF(info, "Number of chips per petal VD: ");
1309 for (int i = 0; i < mNumberOfPetalsVD; i++) {
1310 LOGF(info, "%d", mNumberOfChipsPerPetalVD[i]);
1311 }
1312 LOGF(info, "Number of staves and half staves per layer MLOT: ");
1313 for (int i = 0; i < mNumberOfLayersMLOT; i++) {
1314 std::string mlot = "";
1315 mlot = (i < constants::ML::nLayers) ? "ML" : "OT";
1316 LOGF(info, "Layer: %d, %s, %d staves, %d half staves per stave", i, mlot.c_str(), mNumberOfStaves[i], mNumberOfHalfStaves[i]);
1317 }
1318 LOGF(info, "Number of modules per stave (half stave) in each ML(OT) layer: ");
1319 for (int i = 0; i < mNumberOfLayersMLOT; i++) {
1320 LOGF(info, "%d", mNumberOfModules[i]);
1321 }
1322 LOGF(info, "Number of chips per module MLOT: ");
1323 for (int i = 0; i < mNumberOfLayersMLOT; i++) {
1324 LOGF(info, "%d", mNumberOfChips[i]);
1325 }
1326 LOGF(info, "Number of chips per layer MLOT: ");
1327 for (int i = 0; i < mNumberOfLayersMLOT; i++) {
1328 LOGF(info, "%d", mNumberOfChipsPerLayerMLOT[i]);
1329 }
1330 LOGF(info, "Total number of chips: %d", getNumberOfChips());
1331
1332 /*
1333 std::cout << "mLastChipIndex = [";
1334 for (int i = 0; i < mLastChipIndex.size(); i++) {
1335 std::cout << mLastChipIndex[i];
1336 if (i < mLastChipIndex.size() - 1) {
1337 std::cout << ", ";
1338 }
1339 }
1340 std::cout << "]" << std::endl;
1341 */
1342 std::cout << "mLastChipIndexVD = [";
1343 for (int i = 0; i < mLastChipIndexVD.size(); i++) {
1344 std::cout << mLastChipIndexVD[i];
1345 if (i < mLastChipIndexVD.size() - 1) {
1346 std::cout << ", ";
1347 }
1348 }
1349 std::cout << "]" << std::endl;
1350}
1351
1352//__________________________________________________________________________
1353int GeometryTGeo::getBarrelLayer(int chipID) const
1354{
1355 // for barrel layers only,
1356 // so it would be consistent with number of layers i.e. from 0 to 10,
1357 // starting from VD0 to OT10;
1358 // skip the disks;
1359
1360 int subDetID = getSubDetID(chipID);
1361 int subLayerID = getLayer(chipID);
1362
1363 if (subDetID < 0 || subDetID > 1) {
1364 LOG(error) << "getBarrelLayer(): Invalid subDetID for barrel: " << subDetID
1365 << ". Expected values are 0 or 1.";
1366 return -1;
1367 }
1368
1369 if (subLayerID < 0 || subLayerID > 7) {
1370 LOG(error) << "getBarrelLayer(): Invalid subLayerID for barrel: " << subDetID
1371 << ". Expected values are between 0 and 7.";
1372 return -1;
1373 }
1374
1375 const int baseOffsets[] = {0, 3};
1376
1377 return baseOffsets[subDetID] + subLayerID;
1378}
1379
1380//__________________________________________________________________________
1381void GeometryTGeo::extractSensorXAlphaMLOT(int chipID, float& x, float& alp)
1382{
1383 // works for ML and OT only, a.k.a flat sensors !!!
1384 double locA[3] = {-100., 0., 0.}, locB[3] = {100., 0., 0.}, gloA[3], gloB[3];
1385 double xp{0}, yp{0};
1386
1387 if (getSubDetID(chipID) == 0) {
1388
1389 LOG(error) << "extractSensorXAlphaMLOT(): VD layers are not supported yet! chipID = " << chipID;
1390 return;
1391
1392 } else { // flat sensors, ML and OT
1393 const TGeoHMatrix* matL2G = extractMatrixSensor(chipID);
1394 matL2G->LocalToMaster(locA, gloA);
1395 matL2G->LocalToMaster(locB, gloB);
1396 double dx = gloB[0] - gloA[0], dy = gloB[1] - gloA[1];
1397 double t = (gloB[0] * dx + gloB[1] * dy) / (dx * dx + dy * dy);
1398 xp = gloB[0] - dx * t;
1399 yp = gloB[1] - dy * t;
1400 }
1401
1402 alp = std::atan2(yp, xp);
1403 x = std::hypot(xp, yp);
1404 o2::math_utils::bringTo02Pi(alp);
1405
1407 // once the VD segmentation is done, VD should be added
1408}
1409
1410//__________________________________________________________________________
1412{
1413 // works only for ML & OT
1414 // for VD is yet to be implemented once we have more refined geometry
1415 if (getSubDetID(chipID) == 0) {
1416
1417 LOG(error) << "createT2LMatrixMLOT(): VD layers are not supported yet! chipID = " << chipID
1418 << "returning dummy values! ";
1419 static TGeoHMatrix dummy;
1420 return dummy;
1421
1422 } else {
1423 static TGeoHMatrix t2l;
1424 t2l.Clear();
1425 float alpha = getSensorRefAlphaMLOT(chipID);
1426 t2l.RotateZ(alpha * TMath::RadToDeg());
1427 const TGeoHMatrix* matL2G = extractMatrixSensor(chipID);
1428 const TGeoHMatrix& matL2Gi = matL2G->Inverse();
1429 t2l.MultiplyLeft(&matL2Gi);
1430 return t2l;
1431 }
1432}
1433
1434} // namespace trk
1435} // namespace o2
std::ostringstream debug
int32_t i
uint32_t j
Definition RawData.h:0
Definition of the SegmentationChipclass.
specs of the ALICE3 TRK
Static class with identifiers, bitmasks and names for ALICE detectors.
Definition DetID.h:58
const MatrixCache< Mat3D > & getCacheT2L() const
const char * getName() const
int mSize
prebooked number of sensors
const MatrixCache< Mat3D > & getCacheL2G() const
static const char * composeSymNameModule(int d, int layer)
int extractNumberOfDisksMLOT(int dir) const
Determines the number of active parts in the Geometry.
static const char * getTRKPetalDiskPattern()
int getModule(int index) const
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, not implemented yet.
static const char * composeSymNameChip(int d, int layer)
static std::string sPetalLayerName
static const char * getTRKSensorPattern()
static std::string sStaveName
bool getChipID(int index, int &subDetID, int &petalcase, int &disk, int &lay, int &stave, int &halfstave, int &mod, int &chip) const
std::vector< int > mNumberOfHalfStaves
Number Of Half staves in each stave of the layer in ML/OT.
int extractNumberOfChipsPerPetalVD() const
bool isTrackingFrameCachedMLOT() const
int extractNumberOfHalfStavesMLOT(int lay) const
static const char * getTRKPetalLayerPattern()
int getChip(int index) const
static std::string sFT3ChipName
Chip name.
int extractNumberOfChipsMLOT(int lay) const
std::vector< int > mNumbersOfChipPerDiskVD
numbersOfChipPerDiskVD
std::vector< int > mNumberOfStaves
Number Of Staves per layer in ML/OT barrels.
static const char * getFT3LayerPattern()
Int_t mNumberOfPetalsVD
number of Petals = chip in each VD layer
static std::string sFT3PassiveName
Passive material name.
std::vector< int > mNumberOfModules
Number Of Modules per stave (half stave) in ML/OT.
static std::string sPetalName
int extractNumberOfStavesMLOT(int lay) const
static std::string sPetalDiskName
void Print(Option_t *opt="") const
float getSensorRefAlphaMLOT(int chipId) const
int getLayer(int index) const
local layer index within the sub-detector (0-based per VD/MLOT)
std::vector< unsigned short > mLastChipIndexVD
max ID of the detector in the layer for the VD
static const char * getTRKWrapVolPattern()
std::vector< float > mCacheRefXMLOT
TString getMatrixPath(int index) const
static const char * getTRKPetalAssemblyPattern()
static std::string sFT3VolumeName
Mother volume name.
int getNumberOfChips() const
static const char * getTRKLayerPattern()
static std::string sHalfStaveName
std::vector< unsigned short > mFirstChipIndexStave
Index of first chip on stave (Discs)
unsigned short getFirstChipIndex(int lay, int petalcase, int subDetID) const
std::vector< int > mNumberOfChips
number of chips per module in ML/OT
static std::string sFT3SensorName
Sensor name.
std::vector< unsigned short > mFirstStaveIndexDisc
Index of first stave (abs ID) in each MLOT Disc.
o2::math_utils::Transform3D Mat3D
static std::string sWrapperVolumeName
Wrapper volume name, not implemented at the moment.
static std::string sServiceVolName
TGeoHMatrix & createT2LMatrixMLOT(int)
std::vector< float > mCacheRefAlphaMLOT
cache for X of ML and OT
static const char * getTRKHalfStavePattern()
int extractNumberOfLayersVD() const
std::vector< int > mNumberOfChipsPerPetalVD
numbersOfChipPerPetalVD
static std::string sMetalStackName
static std::string sChipName
static std::string sSensorName
static const char * composeSymNameLayerFT3(int dir, int layer)
void fillMatrixCache(int mask)
std::vector< int > sensorsMLOT
is it owned by the singleton?
static std::string sDeadzoneName
void extractChipIdsFT3(std::string const volName, int &layer, int &stave, int &chip) const
Extract number following the prefix in the name string.
static std::string sLayerName
unsigned short getChipIndex(int subDetID, int petalcase, int disk, int lay, int stave, int halfstave, int mod, int chip) const
int extractNumberOfActivePartsVD() const
void PrintChipID(int index, int subDetID, int petalcase, int disk, int lay, int stave, int halfstave, int mod, int chip) const
static const char * composeSymNameSensor(int d, int layer)
int extractNumberOfModulesMLOT(int lay) const
static std::string sFT3InnerVolumeName
Mother inner volume name.
int extractNumberOfDisksVD() const
static std::string sFT3LayerName
Layer name.
int getLayerTRK(int index) const
global layer index across the full TRK (VD layers 0..nVD-1, MLOT layers nVD..nTotal-1)
static const char * getTRKPetalPattern()
Int_t mNumberOfActivePartsVD
number of layers
std::vector< int > mNumberOfChipsPerLayerMLOT
number of chips per layer MLOT
Int_t mNumberOfDisksVD
number of Disks = 6
Int_t mNumberOfLayersMLOT
number of layers
std::vector< unsigned short > mFirstChipIndexMLOTDisc
ID of the first sensor chip in the layer for the MLOT; array size is one larger than the number of di...
static const char * composeSymNameLayer(int d, int layer)
int getStave(int index) const
int getBarrelLayer(int) const
static const char * getTRKVolPattern()
static const char * getTRKModulePattern()
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
std::vector< unsigned short > mLastChipIndex
max ID of the detector in the petal(VD) or layer(MLOT)
void extractSensorXAlphaMLOT(int, float &, float &)
Int_t mNumberOfDisksMLOT
number of ML/OT disks (12 for v3)
void Build(int loadTrans)
eMLOTLayout mLayoutMLOT
cache for sensor ref alpha ML and OT
Int_t mNumberOfLayersVD
number of layers
int getHalfStave(int index) const
GeometryTGeo(bool build=false, int loadTrans=0)
TGeoHMatrix * extractMatrixSensor(int index) const
static std::string sModuleName
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
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
constexpr int nLayers
Definition Specs.h:105
constexpr int nLayers
Definition Specs.h:123
constexpr int nLayers
Definition Specs.h:47
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
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"