Project
Loading...
Searching...
No Matches
Geometry.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
12#include "PHOSBase/Geometry.h"
13#include <fairlogger/Logger.h>
14#include "TSystem.h"
15#include "TFile.h"
16
17using namespace o2::phos;
18
20
21// module numbering:
22// start from module 0 (non-existing), 1 (half-module), 2 (bottom),... 4(highest)
23// absId:
24// start from 1 till 4*64*56=14336. Numbering in each module starts at bottom left and first go in z direction:
25// 56 112 3584
26// ... ... ...
27// 1 57 ...3529
28// relid[3]: (module number[1...4], iphi[1...64], iz[1...56])
29//
30// TRUabsId channels go from getTotalNCells()+1, 112 per branch, 2 branches per 14 ddl
31// Converting tru absId to relId one gets bottom left corner of 2x2 or 4x4 box
32
33// these initialisations are needed for a singleton
34Geometry* Geometry::sGeom = nullptr;
35
36Geometry::Geometry(const std::string_view name) : mGeoName(name)
37{
38 std::string p = gSystem->Getenv("O2_ROOT");
39 p += "/share/Detectors/PHOS/files/alignment.root";
40 TFile fin(p.data());
41
42 // try reading rotation mathices
43 for (int m = 1; m < 5; m++) {
44 mPHOS[m] = *static_cast<TGeoHMatrix*>(fin.Get(Form("Module%d", m)));
45 }
46 fin.Close();
47}
48
49short Geometry::relToAbsId(char moduleNumber, int strip, int cell)
50{
51 // calculates absolute cell Id from moduleNumber, strip (number) and cell (number)
52 // PHOS layout parameters:
53 const short nStrpZ = 28; // Number of strips along z-axis
54 const short nCrystalsInModule = 56 * 64; // Total number of crystals in module
55 const short nCellsXInStrip = 8; // Number of crystals in strip unit along x-axis
56 const short nZ = 56; // nStripZ * nCellsZInStrip
57
58 short row = nStrpZ - (strip - 1) % nStrpZ;
59 short col = (int)std::ceil((float)strip / (nStrpZ)) - 1;
60
61 return (moduleNumber - 1) * nCrystalsInModule + row * 2 + (col * nCellsXInStrip + (cell - 1) / 2) * nZ -
62 (cell & 1 ? 1 : 0);
63}
64
65bool Geometry::absToRelNumbering(short absId, char* relid)
66{
67 // Converts the absolute numbering into the following array
68 // relid[0] = PHOS Module number 1:fNModules
69 // relid[1] = Row number inside a PHOS module (Z coordinate)
70 // relid[2] = Column number inside a PHOS module (Phi coordinate)
71 const short nZ = 56; // nStripZ * nCellsZInStrip
72 const short nPhi = 64; // nStripZ * nCellsZInStrip
73 absId--;
74 short phosmodulenumber = absId / (nZ * nPhi);
75
76 relid[0] = phosmodulenumber + 1;
77 absId -= phosmodulenumber * nPhi * nZ;
78 relid[1] = 1 + absId / nZ;
79 relid[2] = absId - (relid[1] - 1) * nZ + 1;
80
81 return true;
82}
83bool Geometry::truAbsToRelNumbering(short truId, short trigType, char* relid)
84{
85 // convert trigger cell Id 1..224*14 to relId (same relId schema as for readout channels)
86 // short trigType=0 for 2x2, short trigType=1 for 4x4 trigger
87 // Converting tru absId to relId one gets bottom left corner of 2x2 or 4x4 box
88 truId -= getTotalNCells() + 1; // 1 to start from zero
89 short ddl = truId / 224; // 2*112 channels // DDL id
90 relid[0] = 1 + (ddl + 2) / 4;
91 truId = truId % 224;
92 if (trigType == 1) { // 4x4 trigger
93 if ((truId > 90 && truId < 112) || truId > 202) {
94 LOG(error) << "Wrong TRU id channel " << truId << " should be <91";
95 relid[0] = 0;
96 relid[1] = 0;
97 relid[2] = 0;
98 return false;
99 }
100 relid[1] = 16 * ((2 + ddl) % 4) + 1 + 2 * (truId % 7); // x index
101 if (truId < 112) {
102 relid[2] = 53 - 2 * (truId / 7); // z index branch 0
103 } else {
104 truId -= 112;
105 relid[2] = 25 - 2 * (truId / 7); // z index branch 1
106 }
107 } else { // 2x2 trigger
108 relid[1] = 16 * ((2 + ddl) % 4) + 1 + 2 * (truId % 8); // x index
109 if (truId < 112) {
110 relid[2] = 55 - 2 * (truId / 8); // z index branch 0
111 } else {
112 truId -= 112;
113 relid[2] = 27 - 2 * (truId / 8); // z index branch 1
114 }
115 }
116 return true;
117}
118short Geometry::truRelToAbsNumbering(const char* relId, short trigType)
119{
120 // Convert position in PHOS module to TRU id for 4x4 or 2x2 tiles
121
122 short absId = 0;
123 short ddl = relId[0] * 4 + relId[1] / 16 - 6;
124 if (trigType == 1) { // 4x4 trigger
125 if (relId[2] > 28) {
126 absId = ((53 - relId[2]) / 2) * 7;
127 } else {
128 absId = 112 + ((25 - relId[2]) / 2) * 7;
129 }
130 absId += (((relId[1] - 1) % 16) / 2) % 7;
131 absId += ddl * 224;
132 return getTotalNCells() + absId + 1;
133 } else { // 2x2
134 if (relId[2] > 28) {
135 absId = ((55 - relId[2]) / 2) * 8;
136 } else {
137 absId = 112 + ((27 - relId[2]) / 2) * 8;
138 }
139 absId += (((relId[1] - 1) % 16) / 2) % 8;
140 absId += ddl * 224;
141 return getTotalNCells() + absId + 1;
142 }
143}
144short Geometry::relPosToTruId(char mod, float x, float z, short trigType)
145{
146 // tranform local cluster coordinates to truId
147 char relid[3] = {mod, static_cast<char>(ceil(x / CELLSTEP + 32.499)), static_cast<char>(ceil(z / CELLSTEP + 28.499))};
148 return truRelToAbsNumbering(relid, trigType);
149}
150
151char Geometry::absIdToModule(short absId)
152{
153 const short nZ = 56;
154 const short nPhi = 64;
155
156 return 1 + (absId - 1) / (nZ * nPhi);
157}
158
159int Geometry::areNeighbours(short absId1, short absId2)
160{
161
162 // Gives the neighbourness of two digits = 0 are not neighbour but continue searching
163 // = 1 are neighbour
164 // = 2 are not neighbour but do not continue searching
165 // =-1 are not neighbour, continue searching, but do not look before d2 next
166 // time
167 // neighbours are defined as digits having at least a common vertex
168 // The order of d1 and d2 is important: first (d1) should be a digit already in a cluster
169 // which is compared to a digit (d2) not yet in a cluster
170
171 char relid1[3];
172 absToRelNumbering(absId1, relid1);
173
174 char relid2[3];
175 absToRelNumbering(absId2, relid2);
176
177 if (relid1[0] == relid2[0]) { // inside the same PHOS module
178 char rowdiff = TMath::Abs(relid1[1] - relid2[1]);
179 char coldiff = TMath::Abs(relid1[2] - relid2[2]);
180
181 if (coldiff + rowdiff <= 1) { // Common side
182 return 1;
183 } else {
184 if ((relid2[1] > relid1[1]) && (relid2[2] > relid1[2] + 1)) {
185 return 2; // Difference in row numbers is too large to look further
186 }
187 }
188 return 0;
189
190 } else {
191 if (relid1[0] > relid2[0]) { // we switched to the next module
192 return -1;
193 }
194 return 2;
195 }
196 return 0;
197}
198void Geometry::absIdToRelPosInModule(short absId, float& x, float& z)
199{
200
201 char relid[3];
202 absToRelNumbering(absId, relid);
203
204 x = (relid[1] - 32 - 0.5) * CELLSTEP;
205 z = (relid[2] - 28 - 0.5) * CELLSTEP;
206}
207bool Geometry::relToAbsNumbering(const char* relId, short& absId)
208{
209 const short nZ = 56; // nStripZ * nCellsZInStrip
210 const short nPhi = 64; // nStripZ * nCellsZInStrip
211
212 absId =
213 (relId[0] - 1) * nPhi * nZ + // the offset of PHOS modules
214 (relId[1] - 1) * nZ + // the offset along phi
215 relId[2]; // the offset along z
216
217 return true;
218}
219// local position to absId
220void Geometry::relPosToAbsId(char module, float x, float z, short& absId)
221{
222 // adding 32.5 instead of 32.499 leads to (rare) rounding errors before ceil()
223 char relid[3] = {module, static_cast<char>(ceil(x / CELLSTEP + 32.499)), static_cast<char>(ceil(z / CELLSTEP + 28.499))};
224 relToAbsNumbering(relid, absId);
225}
226void Geometry::relPosToRelId(short module, float x, float z, char* relId)
227{
228 relId[0] = module;
229 relId[1] = static_cast<char>(ceil(x / CELLSTEP + 32.499));
230 relId[2] = static_cast<char>(ceil(z / CELLSTEP + 28.499));
231}
232
233// convert local position in module to global position in ALICE
234void Geometry::local2Global(char module, float x, float z, TVector3& globaPos) const
235{
236 // constexpr float shiftY=-10.76; Run2
237 constexpr float shiftY = -1.26; // Depth-optimized
238 Double_t posL[3] = {x, z, shiftY};
239 Double_t posG[3];
240 mPHOS[module].LocalToMaster(posL, posG);
241 globaPos.SetXYZ(posG[0], posG[1], posG[2]);
242}
243
244bool Geometry::impactOnPHOS(const TVector3& vtx, const TVector3& p,
245 short& module, float& z, float& x) const
246{
247 // calculates the impact coordinates on PHOS of a neutral particle
248 // emitted in the vertex vtx with 3-momentum p
249 constexpr float shiftY = -1.26; // Depth-optimized
250 constexpr float moduleXhalfSize = 72.16; // 18.04 / 2 * 8
251 constexpr float moduleZhalfSize = 64.14; // 4.51 / 2 * 28
252
253 for (short mod = 1; mod < 5; mod++) {
254 // create vector from (0,0,0) to center of crystal surface of imod module
255 double tmp[3] = {0., 0., shiftY};
256 double posG[3] = {0., 0., 0.};
257 mPHOS[mod].LocalToMaster(tmp, posG);
258 TVector3 n(posG[0], posG[1], posG[2]);
259 double direction = n.Dot(p);
260 if (direction <= 0.) {
261 continue; // momentum directed FROM module
262 }
263 double fr = (n.Mag2() - n.Dot(vtx)) / direction;
264 // Calculate direction in module plane
265 n -= vtx + fr * p;
266 n *= -1.;
267 if (TMath::Abs(n.Z()) < moduleZhalfSize && n.Pt() < moduleXhalfSize) {
268 module = mod;
269 z = n.Z();
270 x = TMath::Sign(n.Pt(), n.X());
271 // no need to return to local system since we calcilated distance from module center
272 // and tilts can not be significant.
273 return true;
274 }
275 }
276 // Not in acceptance
277 x = 0;
278 z = 0;
279 module = 0;
280 return false;
281}
ClassImp(Geometry)
uint32_t col
Definition RawData.h:4
static short relPosToTruId(char mod, float x, float z, short trigType)
Definition Geometry.cxx:144
static int getTotalNCells()
Definition Geometry.h:126
static void relPosToAbsId(char module, float x, float z, short &absId)
Definition Geometry.cxx:220
static void relPosToRelId(short module, float x, float z, char *relId)
Definition Geometry.cxx:226
void local2Global(char module, float x, float z, TVector3 &globaPos) const
Definition Geometry.cxx:234
bool impactOnPHOS(const TVector3 &vtx, const TVector3 &p, short &module, float &z, float &x) const
Definition Geometry.cxx:244
static char absIdToModule(short absId)
Definition Geometry.cxx:151
static int areNeighbours(short absId1, short absId2)
Definition Geometry.cxx:159
static short truRelToAbsNumbering(const char *relId, short trigType)
Definition Geometry.cxx:118
static void absIdToRelPosInModule(short absId, float &x, float &z)
Definition Geometry.cxx:198
static bool relToAbsNumbering(const char *RelId, short &AbsId)
Definition Geometry.cxx:207
static short relToAbsId(char moduleNumber, int strip, int cell)
Definition Geometry.cxx:49
static bool truAbsToRelNumbering(short truId, short trigType, char *relid)
Definition Geometry.cxx:83
static bool absToRelNumbering(short absId, char *relid)
Definition Geometry.cxx:65
GLdouble n
Definition glcorearb.h:1982
GLint GLenum GLint x
Definition glcorearb.h:403
const GLfloat * m
Definition glcorearb.h:4066
GLuint const GLchar * name
Definition glcorearb.h:781
GLdouble GLdouble GLdouble z
Definition glcorearb.h:843
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::vector< int > row