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) {
114 auto layerVol = layerNode->GetVolume();
115 if (layerVol ==
nullptr)
117 TObjArray*
nodes = layerVol->GetNodes();
118 int nNodes =
nodes->GetEntriesFast();
121 std::vector<int> chipsPerStave;
122 for (
int j = 0;
j < nNodes;
j++) {
123 auto nd =
dynamic_cast<TGeoNode*
>(
nodes->At(
j));
124 const char*
name = nd->GetName();
125 if (strstr(
name,
"FT3Sensor") !=
nullptr && strstr(
name,
"Inactive") ==
nullptr) {
126 int direction = 0,
layer = 0;
127 int stave = 0, chip = 0;
129 if (stave >= chipsPerStave.size()) {
130 chipsPerStave.resize(stave + 1, 0);
133 if (chip + 1 >= chipsPerStave[stave]) {
134 chipsPerStave[stave] = chip + 1;
139 LOG(info) <<
"direction " << iDir <<
" disc " << iDisc <<
" has " << nNodes <<
" nodes of which " << nSensor <<
" sensors in " << chipsPerStave.size() <<
" staves";
141 if (nStaves != chipsPerStave.size()) {
142 LOG(info) <<
"Inconsistency in stave count " << nStaves <<
" " << chipsPerStave.size();
144 mChipIdxStave.resize(absStaveIdx + chipsPerStave.size() + 1);
147 for (
int nChips : chipsPerStave) {
148 LOG(
debug) <<
"Absolute Stave ID " << absStaveIdx <<
" : " << nChips <<
" sensors";
155 if (totSensor != nSensor) {
156 LOG(info) <<
"Inconsistency in sensor count " << nSensor <<
" " << totSensor;
158 LOG(
debug) <<
" adding stave Idx " << absStaveIdx <<
" to disc array; element " <<
mStaveIdxDisc.size();
162 LOG(info) <<
"Total sensors so far " <<
mSize;
166 LOG(info) <<
"Total sensors " <<
mSize;
203 if (ft3V ==
nullptr) {
207 TObjArray*
nodes = layerVol->GetNodes();
208 int nNodes =
nodes->GetEntriesFast();
210 for (
int j = 0;
j < nNodes;
j++) {
211 auto nd =
dynamic_cast<TGeoNode*
>(
nodes->At(
j));
212 const char*
name = nd->GetName();
213 if (strstr(
name,
"FT3Sensor") !=
nullptr && strstr(
name,
"Inactive") ==
nullptr) {
217 LOG(info) <<
"direction " << dir <<
" layer " <<
layer <<
" has " << nNodes <<
" nodes of which " << nSensor <<
" sensors";
223 if (volName.find(
"FT3Sensor_Active") == 0) {
224 return std::stoi(volName.substr(volName.rfind(
'_') + 1));
226 LOG(error) <<
"Not a sensor volume " << volName;
231 if (volName.find(
"FT3Sensor_Active") == 0) {
232 int idx = volName.rfind(
'_');
233 chip = std::stoi(volName.substr(idx + 1));
234 idx = volName.rfind(
'_', idx);
235 stave = std::stoi(volName.substr(idx + 1));
237 LOG(error) <<
"Not a sensor volume " << volName;
244 if (volName.find(
"FT3Sensor_Active") == 0) {
245 int idx = volName.find(
'_') + 1;
246 idx = volName.find(
'_', idx) + 1;
247 direction = std::stoi(volName.substr(idx));
248 idx = volName.find(
'_', idx) + 1;
249 layer = std::stoi(volName.substr(idx));
250 idx = volName.find(
'_', idx) + 1;
251 stave = std::stoi(volName.substr(idx));
252 idx = volName.find(
'_', idx) + 1;
253 chip = std::stoi(volName.substr(idx));
255 LOG(error) <<
"Not a sensor volume " << volName;
311 path += Form(
"FT3Sensor_Active_%d_%d_%d_%d_%d", direction,
layer, stave, chip, chip);
331 LOG(warning) <<
"The method Build was not called yet";
339 LOGP(info,
"Loading {} L2G matrices from TGeo; there are {} matrices",
getName(),
mSize);
341 cacheL2G.setSize(
mSize);
343 cacheT2L.setSize(
mSize);
346 double locA[3] = {-100., 0., 0.}, locB[3] = {100., 0., 0.}, gloA[3], gloB[3];
349 gGeoManager->PushPath();
352 for (
int absDisc = 0; absDisc < nTotDisc; absDisc++) {
359 LOG(info) <<
"Direction " << direction <<
" layer " <<
layer;
366 LOG(fatal) <<
"Attempting to get absStave + 1 from index array size " <<
mChipIdxStave.size();
369 LOG(
debug) <<
"Getting matrices for direction " << direction <<
" layer " <<
layer <<
" stave " << stave <<
" : " << nChip <<
" chips";
370 for (
int chip = 0; chip < nChip; chip++) {
375 const TGeoHMatrix* matL2G = gGeoManager->GetCurrentMatrix();
376 if (chipIdx >=
mSize) {
377 LOG(fatal) <<
"ChipIdx " << chipIdx <<
" out of range " <<
mSize;
379 cacheL2G.setMatrix(
Mat3D(*matL2G), chipIdx);
381 matL2G->LocalToMaster(locA, gloA);
382 matL2G->LocalToMaster(locB, gloB);
383 double dx = gloB[0] - gloA[0], dy = gloB[1] - gloA[1];
384 double t = (gloB[0] * dx + gloB[1] * dy) / (dx * dx + dy * dy);
385 xp = gloB[0] - dx * t;
386 yp = gloB[1] - dy * t;
387 float alp = std::atan2(yp, xp);
389 o2::math_utils::bringTo02Pi(alp);
392 static TGeoHMatrix t2l;
395 const TGeoHMatrix& matL2Gi = matL2G->Inverse();
396 t2l.MultiplyLeft(&matL2Gi);
397 cacheT2L.setMatrix(
Mat3D(t2l), chipIdx);
401 gGeoManager->PopPath();
409 LOGF(info,
"Geometry not built yet!");
412 std::cout <<
"Detector ID: " << sInstance.get()->getDetID() << std::endl;
414 LOGF(info,
"Summary of GeometryTGeo: %s",
getName());
416 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"