16#include <fairlogger/Logger.h>
19#include <TGeoManager.h>
20#include <TGeoPhysicalNode.h>
25#include "TGeoMatrix.h"
27#include "TGeoVolume.h"
43std::unique_ptr<o2::ft3::GeometryTGeo> GeometryTGeo::sInstance;
66 LOG(fatal) <<
"Invalid use of public constructor: o2::ft3::GeometryTGeo instance exists";
79 LOG(warning) <<
"Already built";
85 LOG(fatal) <<
"Geometry is not loaded";
100 for (
int iDir = 0; iDir < 2; iDir++) {
102 LOG(info) <<
"direction " << iDir <<
" has " <<
mNumberOfDiscs[iDir] <<
" discs";
107 if (ft3V ==
nullptr) {
111 if (layerNode ==
nullptr)
113 auto layerVol = layerNode->GetVolume();
114 if (layerVol ==
nullptr)
116 TObjArray*
nodes = layerVol->GetNodes();
117 int nNodes =
nodes->GetEntriesFast();
120 std::vector<int> chipsPerStave;
121 for (
int j = 0;
j < nNodes;
j++) {
122 auto nd =
dynamic_cast<TGeoNode*
>(
nodes->At(
j));
123 const char*
name = nd->GetName();
124 if (strstr(
name,
"FT3Sensor") !=
nullptr && strstr(
name,
"Inactive") ==
nullptr) {
125 int direction = 0,
layer = 0;
126 int stave = 0, chip = 0;
128 if (stave >= chipsPerStave.size()) {
129 chipsPerStave.resize(stave + 1, 0);
132 if (chip + 1 >= chipsPerStave[stave]) {
133 chipsPerStave[stave] = chip + 1;
138 LOG(info) <<
"direction " << iDir <<
" disc " << iDisc <<
" has " << nNodes <<
" nodes of which " << nSensor <<
" sensors in " << chipsPerStave.size() <<
" staves";
140 if (nStaves != chipsPerStave.size())
141 LOG(info) <<
"Inconsistency in stave count " << nStaves <<
" " << chipsPerStave.size();
142 mChipIdxStave.resize(absStaveIdx + chipsPerStave.size() + 1);
145 for (
int nChips : chipsPerStave) {
146 LOG(
debug) <<
"Absolute Stave ID " << absStaveIdx <<
" : " << nChips <<
" sensors";
152 if (totSensor != nSensor)
153 LOG(info) <<
"Inconsistency in sensor count " << nSensor <<
" " << totSensor;
154 LOG(
debug) <<
" adding stave Idx " << absStaveIdx <<
" to disc array; element " <<
mStaveIdxDisc.size();
158 LOG(info) <<
"Total sensors so far " <<
mSize;
162 LOG(info) <<
"Total sensors " <<
mSize;
199 if (ft3V ==
nullptr) {
203 TObjArray*
nodes = layerVol->GetNodes();
204 int nNodes =
nodes->GetEntriesFast();
206 for (
int j = 0;
j < nNodes;
j++) {
207 auto nd =
dynamic_cast<TGeoNode*
>(
nodes->At(
j));
208 const char*
name = nd->GetName();
209 if (strstr(
name,
"FT3Sensor") !=
nullptr && strstr(
name,
"Inactive") ==
nullptr) {
213 LOG(info) <<
"direction " << dir <<
" layer " <<
layer <<
" has " << nNodes <<
" nodes of which " << nSensor <<
" sensors";
219 if (volName.find(
"FT3Sensor_Active") == 0) {
220 return std::stoi(volName.substr(volName.rfind(
'_') + 1));
222 LOG(error) <<
"Not a sensor volume " << volName;
227 if (volName.find(
"FT3Sensor_Active") == 0) {
228 int idx = volName.rfind(
'_');
229 chip = std::stoi(volName.substr(idx + 1));
230 idx = volName.rfind(
'_', idx);
231 stave = std::stoi(volName.substr(idx + 1));
233 LOG(error) <<
"Not a sensor volume " << volName;
240 if (volName.find(
"FT3Sensor_Active") == 0) {
241 int idx = volName.find(
'_') + 1;
242 idx = volName.find(
'_', idx) + 1;
243 direction = std::stoi(volName.substr(idx));
244 idx = volName.find(
'_', idx) + 1;
245 layer = std::stoi(volName.substr(idx));
246 idx = volName.find(
'_', idx) + 1;
247 stave = std::stoi(volName.substr(idx));
248 idx = volName.find(
'_', idx) + 1;
249 chip = std::stoi(volName.substr(idx));
251 LOG(error) <<
"Not a sensor volume " << volName;
306 path += Form(
"FT3Sensor_Active_%d_%d_%d_%d_%d", direction,
layer, stave, chip, chip);
326 LOG(warning) <<
"The method Build was not called yet";
334 LOGP(info,
"Loading {} L2G matrices from TGeo; there are {} matrices",
getName(),
mSize);
336 cacheL2G.setSize(
mSize);
338 cacheT2L.setSize(
mSize);
341 double locA[3] = {-100., 0., 0.}, locB[3] = {100., 0., 0.}, gloA[3], gloB[3];
344 gGeoManager->PushPath();
347 for (
int absDisc = 0; absDisc < nTotDisc; absDisc++) {
354 LOG(info) <<
"Direction " << direction <<
" layer " <<
layer;
360 LOG(fatal) <<
"Attempting to get absStave + 1 from index array size " <<
mChipIdxStave.size();
362 LOG(
debug) <<
"Getting matrices for direction " << direction <<
" layer " <<
layer <<
" stave " << stave <<
" : " << nChip <<
" chips";
363 for (
int chip = 0; chip < nChip; chip++) {
367 const TGeoHMatrix* matL2G = gGeoManager->GetCurrentMatrix();
368 if (chipIdx >=
mSize)
369 LOG(fatal) <<
"ChipIdx " << chipIdx <<
" out of range " <<
mSize;
370 cacheL2G.setMatrix(
Mat3D(*matL2G), chipIdx);
372 matL2G->LocalToMaster(locA, gloA);
373 matL2G->LocalToMaster(locB, gloB);
374 double dx = gloB[0] - gloA[0], dy = gloB[1] - gloA[1];
375 double t = (gloB[0] * dx + gloB[1] * dy) / (dx * dx + dy * dy);
376 xp = gloB[0] - dx * t;
377 yp = gloB[1] - dy * t;
378 float alp = std::atan2(yp, xp);
380 o2::math_utils::bringTo02Pi(alp);
383 static TGeoHMatrix t2l;
386 const TGeoHMatrix& matL2Gi = matL2G->Inverse();
387 t2l.MultiplyLeft(&matL2Gi);
388 cacheT2L.setMatrix(
Mat3D(t2l), chipIdx);
392 gGeoManager->PopPath();
400 LOGF(info,
"Geometry not built yet!");
403 std::cout <<
"Detector ID: " << sInstance.get()->getDetID() << std::endl;
405 LOGF(info,
"Summary of GeometryTGeo: %s",
getName());
407 LOGF(info,
"Total number of sensors: %d",
mSize);
Definition of the GeometryTGeo class.
Static class with identifiers, bitmasks and names for ALICE detectors.
const MatrixCache< Mat3D > & getCacheT2L() const
const char * getName() const
int mSize
prebooked number of sensors
const MatrixCache< Mat3D > & getCacheL2G() const
int extractNumberOfDiscs(int dir)
std::vector< float > mCacheRefXDiscs
static std::string sPassiveName
Passive material name.
static std::string sChipName
Chip name.
void extractChipIds(std::string const volName, int &direction, int &layer, int &stave, int &chip)
std::vector< int > mNumberOfChipsPerDisc
Index of first chup for each global stave.
void Build(int loadTrans)
static const char * composeSymNameSensor(Int_t d, Int_t lr)
static std::string sLayerName
Layer name.
static const char * getFT3SensorPattern()
o2::math_utils::Transform3D Mat3D
void Print(Option_t *opt="") const
static std::string sVolumeName
Mother volume name.
void fillMatrixCache(int mask)
int getChipOnStave(int chipIdx) const
static const char * getFT3ChipPattern()
std::vector< int > mNumberOfStavesPerDisc
static std::string sSensorName
Sensor name.
GeometryTGeo(bool build=false, int loadTrans=0)
static const char * composeSymNameLayer(Int_t d, Int_t lr)
int getStave(int chipIdx) const
int extractNumberOfChips(int dir, int layer)
std::vector< int > mChipIdxStave
Index of first global stave Id for each disc.
static std::string sInnerVolumeName
Mother inner volume name.
std::vector< float > mCacheRefAlphaDiscs
cache for X of ML and OT
std::vector< int > mStaveIdxDisc
TODO; in principle redundant?
static const char * getFT3LayerPattern()
static const char * composeSymNameChip(Int_t d, Int_t lr)
int extractChipId(std::string const volName)
std::vector< int > mNumberOfDiscs
cache for sensor ref alpha ML and OT
void extractStaveChipId(std::string const volName, int &stave, int &chip)
int getLayer(int chipIdx) const
static const char * getFT3VolPattern()
int getChipIndex(int dir, int disc, int stave, int chip) const
std::string getMatrixPath(int direction, int layer, int stave, int chip) const
GLuint const GLchar * name
GLsizei const GLchar *const * path
GLenum GLuint GLint GLint layer
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"