EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CylinderGeom_Mvtx.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file CylinderGeom_Mvtx.cc
1 #include "CylinderGeom_Mvtx.h"
2 
3 #include "SegmentationAlpide.h"
4 
5 #include <TRotation.h>
6 #include <TVector3.h>
7 
8 #include <cmath>
9 #include <ostream> // for operator<<, basic_ostream::operator<<, basic_...
10 
11 using namespace std;
13 
15  int in_layer,
16  int in_N_staves,
17  double in_layer_nominal_radius,
18  double in_phistep,
19  double in_phitilt,
20  double in_phi0)
21  : layer(in_layer)
22  , N_staves(in_N_staves)
23  , N_half_staves(0)
24  , layer_radius(in_layer_nominal_radius)
25  , stave_phi_step(in_phistep)
26  , stave_phi_tilt(in_phitilt)
27  , stave_phi_0(in_phi0)
28  , pixel_x(Segmentation::PitchRow)
29  , pixel_z(Segmentation::PitchCol)
30  , pixel_thickness(Segmentation::SensorLayerThickness)
31 {
32  // Note that stave is centered at origin with normal to face of sensor pointing in +y direction
33  // Units here are cm, same as in the gdml file
34 
35  // for all layers
36  double loc_sensor_in_chip_data[3] = {0.058128, -0.0005, 0.0}; // mvtx_stave_v1.gdml
37 
38  for (int i = 0; i < 3; i++)
39  loc_sensor_in_chip[i] = loc_sensor_in_chip_data[i];
40 
41  // inner barrel layers stave construction
42  //==========================
43  // from mvtx_stave_v1.gdml
44  // chip 0 is the closet to connectors (-Z)
45  double inner_loc_chip_in_module_data[9][3] = {
46  {0.0275, -0.02075, -12.060},
47  {0.0275, -0.02075, -9.0450},
48  {0.0275, -0.02075, -6.0300},
49  {0.0275, -0.02075, -3.0150},
50  {0.0275, -0.02075, 0.0},
51  {0.0275, -0.02075, 3.0150},
52  {0.0275, -0.02075, 6.0300},
53  {0.0275, -0.02075, 9.0450},
54  {0.0275, -0.02075, 12.060}};
55 
56  double inner_loc_module_in_halfstave_data[3] = {0.0, 0.0, 0.0}; // only one module
57 
58  double inner_loc_halfstave_in_stave_data[3] = {-0.0275, 0.01825, 0.0};
59 
60  for (int i = 0; i < 3; i++)
61  {
62  inner_loc_module_in_halfstave[i] = inner_loc_module_in_halfstave_data[i];
63  inner_loc_halfstave_in_stave[i] = inner_loc_halfstave_in_stave_data[i];
64  for (int j = 0; j < 9; j++)
65  {
66  inner_loc_chip_in_module[j][i] = inner_loc_chip_in_module_data[j][i];
67  }
68  }
69 
70  return;
71 }
72 
73 TVector3
74 CylinderGeom_Mvtx::get_local_from_world_coords(int stave, int /*half_stave*/, int /*module*/, int chip, TVector3 world_location)
75 {
76  double stave_phi = stave_phi_0 + stave_phi_step * (double) stave;
77  double stave_phi_offset = M_PI / 2.0; // stave initially points so that sensor faces upward in y
78 
79  // Starting from its location in the world
80  TVector3 res = world_location;
81 
82  // transform location of stave from its location in the world - this is just a translation
83  TVector3 tr4(layer_radius * cos(stave_phi), layer_radius * sin(stave_phi), 0.0);
84  res -= tr4;
85 
86  // Rotate stave from its angle in the world
87  // This requires rotating it by:
88  // removing the tilt
89  // removing the offsetfor first layer
90  // removing the angle that makes it point at the origin when it was at it's location in the world
91  // rotating it by -90 degrees to make the face point vertically up in y
92  TRotation R;
93  R.RotateZ(-stave_phi - stave_phi_offset - stave_phi_tilt);
94  res = R * res; // rotates res using R
95 
96  // transform location in stave to location in half stave
97  TVector3 tr3(inner_loc_halfstave_in_stave[0],
100  res -= tr3;
101 
102  // transfor from half stave to location in module
103  TVector3 tr2a(inner_loc_module_in_halfstave[0],
106  res -= tr2a;
107 
108  // transform location in module to location in chip
109  TVector3 tr2(inner_loc_chip_in_module[chip][0],
110  inner_loc_chip_in_module[chip][1],
111  inner_loc_chip_in_module[chip][2]);
112  res -= tr2;
113 
114  // transform location in chip to location in sensor
115  TVector3 tr1(loc_sensor_in_chip[0],
117  loc_sensor_in_chip[2]);
118  res -= tr1;
119 
120  return res;
121 }
122 
123 void
124 CylinderGeom_Mvtx::get_sensor_indices_from_world_coords(std::vector<double> &world, unsigned int &stave_index, unsigned int &chip_index)
125 {
126  // stave number is fom phi
127  double phi = atan2(world[1], world[0]);
128  if(phi < 0) phi += 2.0*M_PI;
129  //int stave_tmp = (int) ( (phi - stave_phi_0) / stave_phi_step );
130  int stave_tmp = round( (phi - stave_phi_0) / stave_phi_step );
131  //std::cout << " phi " << phi << " stave_phi_0 " << stave_phi_0 << " stave_phi_step " << stave_phi_step << " stave_tmp " << stave_tmp << std::endl;
132 
133  // sensor is from z
134  double chip_delta_z = (inner_loc_chip_in_module[8][2] - inner_loc_chip_in_module[0][2]) / 8.0;
135  //int chip_tmp = (int) (world[2]/chip_delta_z) + 4; // 0-9
136  int chip_tmp = round(world[2]/chip_delta_z) + 4; // 0-9
137  //std::cout << " z " << world[2] << " chip_delta_z " << chip_delta_z << " chip_tmp " << chip_tmp << endl;
138 
139  stave_index = stave_tmp;
140  chip_index = chip_tmp;
141 }
142 
143 TVector3
144 CylinderGeom_Mvtx::get_world_from_local_coords(int stave, int /*half_stave*/, int /*module*/, int chip, TVector3 sensor_local)
145 {
146  double stave_phi = stave_phi_0 + stave_phi_step * (double) stave;
147  double stave_phi_offset = M_PI / 2.0; // stave initially points so that sensor faces upward in y
148 
149  // Start with the point in sensor local coords
150  TVector3 res = sensor_local;
151 
152  // transform sensor location to location in chip
153  TVector3 tr1(loc_sensor_in_chip[0],
155  loc_sensor_in_chip[2]);
156  res += tr1;
157 
158  // transform location in chip to location in module
159  TVector3 tr2(inner_loc_chip_in_module[chip][0],
160  inner_loc_chip_in_module[chip][1],
161  inner_loc_chip_in_module[chip][2]);
162  res += tr2;
163 
164  // module to half stave
165  TVector3 tr2a(inner_loc_module_in_halfstave[0],
168  res += tr2a;
169 
170  // transform location in half stave to location in stave
171  TVector3 tr3(inner_loc_halfstave_in_stave[0],
174  res += tr3;
175 
176  // Rotate stave to its angle in the world
177  // This requires rotating it by
178  // 90 degrees to make the face point to the origin instead of vertically up in y when it is at phi = 0 - stave_phi_offset is 90 degrees in CCW direction
179  // Rotating it fiurther so that it points at the origin after being translated to the x and y coords of the stave phi location - stave_phi derived from
180  // stave_phi_step and stave (number), both constructor parameters
181  // Adding the tilt (for layers 0-2) - stave_phi_tilt is a constructor parameter provided by PHG4MvtxDetector
182  // for a rotation
183  TRotation R;
184  R.RotateZ(stave_phi + stave_phi_offset + stave_phi_tilt);
185  res = R * res; // rotates res using R
186 
187  // transform location of stave to its location in the world
188  TVector3 tr4(layer_radius * cos(stave_phi),
189  layer_radius * sin(stave_phi),
190  0.0);
191  res += tr4;
192 
193  return res;
194 }
195 
196 bool CylinderGeom_Mvtx::get_pixel_from_local_coords(TVector3 sensor_local, int& iRow, int& iCol)
197 {
198  //YCM (2020-01-02): It seems that due some round issues, local coords of hits at the edge of the sensor volume
199  // are out by some fraction of microns from the ActiveMatrix. Making a safety check inside 0.1 um
200  double EPS = 5e-6;
201  if ( fabs(fabs(sensor_local.X()) - SegmentationAlpide::ActiveMatrixSizeRows/2.f) < EPS ){
202  //cout << " Adjusting X, before X= " << sensor_local.X() << endl;
203  sensor_local.SetX( ((sensor_local.X() < 0 ) ? -1 : 1) * (SegmentationAlpide::ActiveMatrixSizeRows/2.f - EPS) );
204  //cout << " Adjusting X, after X= " << sensor_local.X() << endl;
205  }
206  if ( fabs(fabs(sensor_local.Z()) - SegmentationAlpide::ActiveMatrixSizeCols/2.f) < EPS ){
207  //cout << " Adjusting Z, before Z= " << sensor_local.Z() << endl;
208  sensor_local.SetZ( ((sensor_local.Z() < 0 ) ? -1 : 1) * (SegmentationAlpide::ActiveMatrixSizeCols/2.f - EPS) );
209  //cout << " Adjusting Z, after Z= " << sensor_local.Z() << endl;
210  }
211  // YCM (2020-01-02): go from sensor to chip local coords
212  TVector3 in_chip = sensor_local;
214  in_chip += tr;
215 
216  return SegmentationAlpide::localToDetector(in_chip.X(), in_chip.Z(), iRow, iCol);
217 }
218 
220 {
221  int Ngridx, Ngridz;
222  bool px_in = get_pixel_from_local_coords(sensor_local, Ngridx, Ngridz);
223  if (!px_in)
224  cout << PHWHERE
225  << " Pixel is out sensor. ("
226  << sensor_local.X() << ", "
227  << sensor_local.Y() << ", "
228  << sensor_local.Z() << ")."
229  << endl;
230 
231  if (Ngridx < 0 || Ngridx >= get_NX() || Ngridz < 0 || Ngridz >= get_NZ())
232  cout << PHWHERE << "Wrong pixel value X= " << Ngridx << " and Z= " << Ngridz << endl;
233 
234  // numbering starts at zero
235  return Ngridx + Ngridz * get_NX();
236 }
237 
239 {
240  int Ngridz = NXZ / get_NX();
241  int Ngridx = NXZ % get_NX();
242 
243  return get_local_coords_from_pixel(Ngridx, Ngridz);
244 }
245 
247 {
248  TVector3 local;
249  bool check = SegmentationAlpide::detectorToLocal((float)iRow, (float)iCol, local);
250  if ( ! check)
251  cout << PHWHERE << "Pixel coord ( " << iRow << ", " << iCol <<" )" << "out of range" << endl;
252  // Transform location in chip to location in sensors
253  TVector3 trChipToSens(loc_sensor_in_chip[0],
255  loc_sensor_in_chip[2]);
256  local -= trChipToSens;
257  return local;
258 }
259 
260 void CylinderGeom_Mvtx::identify(std::ostream& os) const
261 {
262  os << "CylinderGeom_Mvtx: layer: " << layer
263  << ", layer_radius: " << layer_radius
264  << ", N_staves in layer: " << N_staves
265  << ", N_half_staves in layer: " << N_half_staves
266  << ", pixel_x: " << pixel_x
267  << ", pixel_z: " << pixel_z
268  << ", pixel_thickness: " << pixel_thickness
269  << endl;
270  return;
271 }
272 
273 void CylinderGeom_Mvtx::find_sensor_center(int stave, int half_stave, int module, int chip, double location[])
274 {
275  TVector3 sensor_local(0.0, 0.0, 0.0);
276 
277  TVector3 sensor_world = get_world_from_local_coords(stave, half_stave, module, chip, sensor_local);
278 
279  location[0] = sensor_world.X();
280  location[1] = sensor_world.Y();
281  location[2] = sensor_world.Z();
282 
283  return;
284 }
285 
286 // hide SegmentationAlpide include from root5 rootcint (rootcling is fine)
288 {
290 }
291 
293 {
295 }
296 
298 {
299  return NXZ % get_NX();
300 }
301 
303 {
304  return NXZ / get_NX();
305 }
306 
307 int CylinderGeom_Mvtx::get_pixel_number_from_xbin_zbin(int xbin, int zbin) // obsolete
308 {
309  return xbin + zbin * get_NX();
310 }