Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-06 08:17:54

0001 #include "CylinderGeom_Mvtx.h"
0002 
0003 #include "SegmentationAlpide.h"
0004 
0005 #include <TRotation.h>
0006 #include <TVector3.h>
0007 
0008 #include <cmath>
0009 #include <ostream>  // for operator<<, basic_ostream::operator<<, basic_...
0010 
0011 using namespace std;
0012 using Segmentation = SegmentationAlpide;
0013 
0014 CylinderGeom_Mvtx::CylinderGeom_Mvtx(
0015     int in_layer,
0016     int in_N_staves,
0017     double in_layer_nominal_radius,
0018     double in_phistep,
0019     double in_phitilt,
0020     double in_phi0)
0021   : layer(in_layer)
0022   , N_staves(in_N_staves)
0023   , N_half_staves(0)
0024   , layer_radius(in_layer_nominal_radius)
0025   , stave_phi_step(in_phistep)
0026   , stave_phi_tilt(in_phitilt)
0027   , stave_phi_0(in_phi0)
0028   , pixel_x(Segmentation::PitchRow)
0029   , pixel_z(Segmentation::PitchCol)
0030   , pixel_thickness(Segmentation::SensorLayerThickness)
0031 {
0032   // Note that stave is centered at origin with normal to face of sensor pointing in +y direction
0033   // Units here are cm, same as in the gdml file
0034 
0035   // for all layers
0036   double loc_sensor_in_chip_data[3] = {0.058128, -0.0005, 0.0};  // mvtx_stave_v1.gdml
0037 
0038   for (int i = 0; i < 3; i++)
0039   {
0040     loc_sensor_in_chip[i] = loc_sensor_in_chip_data[i];
0041   }
0042 
0043   // inner barrel layers stave construction
0044   //==========================
0045   // from mvtx_stave_v1.gdml
0046   // chip 0 is the closet to connectors (-Z)
0047   double inner_loc_chip_in_module_data[9][3] = {
0048       {0.0275, -0.02075, -12.060},
0049       {0.0275, -0.02075, -9.0450},
0050       {0.0275, -0.02075, -6.0300},
0051       {0.0275, -0.02075, -3.0150},
0052       {0.0275, -0.02075, 0.0},
0053       {0.0275, -0.02075, 3.0150},
0054       {0.0275, -0.02075, 6.0300},
0055       {0.0275, -0.02075, 9.0450},
0056       {0.0275, -0.02075, 12.060}};
0057 
0058   double inner_loc_module_in_halfstave_data[3] = {0.0, 0.0, 0.0};  // only one module
0059 
0060   double inner_loc_halfstave_in_stave_data[3] = {-0.0275, 0.01825, 0.0};
0061 
0062   for (int i = 0; i < 3; i++)
0063   {
0064     inner_loc_module_in_halfstave[i] = inner_loc_module_in_halfstave_data[i];
0065     inner_loc_halfstave_in_stave[i] = inner_loc_halfstave_in_stave_data[i];
0066     for (int j = 0; j < 9; j++)
0067     {
0068       inner_loc_chip_in_module[j][i] = inner_loc_chip_in_module_data[j][i];
0069     }
0070   }
0071 
0072   return;
0073 }
0074 
0075 void CylinderGeom_Mvtx::get_sensor_indices_from_world_coords(std::vector<double>& world, unsigned int& stave_index, unsigned int& chip_index)
0076 {
0077   // stave number is fom phi
0078   double phi = atan2(world[1], world[0]);
0079   if (phi < 0)
0080   {
0081     phi += 2.0 * M_PI;
0082   }
0083 
0084   // int stave_tmp = (int) ( (phi - stave_phi_0) / stave_phi_step );
0085   int stave_tmp = round((phi - stave_phi_0) / stave_phi_step);
0086   // std::cout << "  phi " << phi << " stave_phi_0 " << stave_phi_0 << " stave_phi_step " << stave_phi_step << " stave_tmp " << stave_tmp << std::endl;
0087 
0088   // sensor is from z
0089   double chip_delta_z = (inner_loc_chip_in_module[8][2] - inner_loc_chip_in_module[0][2]) / 8.0;
0090   // int chip_tmp = (int) (world[2]/chip_delta_z) + 4;  // 0-9
0091   int chip_tmp = round(world[2] / chip_delta_z) + 4;  // 0-9
0092   // std::cout << "  z " << world[2] << " chip_delta_z " << chip_delta_z << " chip_tmp " << chip_tmp << endl;
0093 
0094   stave_index = stave_tmp;
0095   chip_index = chip_tmp;
0096 }
0097 
0098 bool CylinderGeom_Mvtx::get_pixel_from_local_coords(TVector3 sensor_local, int& iRow, int& iCol)
0099 {
0100   // YCM (2020-01-02): It seems that due some round issues, local coords of hits at the edge of the sensor volume
0101   //                   are out by some fraction of microns from the ActiveMatrix. Making a safety check inside 0.1 um
0102   double EPS = 5e-6;
0103   if (fabs(fabs(sensor_local.X()) - SegmentationAlpide::ActiveMatrixSizeRows / 2.F) < EPS)
0104   {
0105     // cout << " Adjusting X,  before X= " << sensor_local.X() << endl;
0106     sensor_local.SetX(((sensor_local.X() < 0) ? -1 : 1) * (SegmentationAlpide::ActiveMatrixSizeRows / 2.F - EPS));
0107     // cout << " Adjusting X,  after X= " << sensor_local.X() << endl;
0108   }
0109   if (fabs(fabs(sensor_local.Z()) - SegmentationAlpide::ActiveMatrixSizeCols / 2.F) < EPS)
0110   {
0111     // cout << " Adjusting Z,  before Z= " << sensor_local.Z() << endl;
0112     sensor_local.SetZ(((sensor_local.Z() < 0) ? -1 : 1) * (SegmentationAlpide::ActiveMatrixSizeCols / 2.F - EPS));
0113     // cout << " Adjusting Z,  after Z= " << sensor_local.Z() << endl;
0114   }
0115   // YCM (2020-01-02): go from sensor to chip local coords
0116   TVector3 in_chip = sensor_local;
0117   TVector3 tr(loc_sensor_in_chip[0], loc_sensor_in_chip[1], loc_sensor_in_chip[2]);
0118   in_chip += tr;
0119 
0120   return SegmentationAlpide::localToDetector(in_chip.X(), in_chip.Z(), iRow, iCol);
0121 }
0122 
0123 int CylinderGeom_Mvtx::get_pixel_from_local_coords(const TVector3& sensor_local)
0124 {
0125   int Ngridx, Ngridz;
0126   bool px_in = get_pixel_from_local_coords(sensor_local, Ngridx, Ngridz);
0127   if (!px_in)
0128   {
0129     cout << PHWHERE
0130          << " Pixel is out sensor. ("
0131          << sensor_local.X() << ", "
0132          << sensor_local.Y() << ", "
0133          << sensor_local.Z() << ")."
0134          << endl;
0135   }
0136 
0137   if (Ngridx < 0 || Ngridx >= get_NX() || Ngridz < 0 || Ngridz >= get_NZ())
0138   {
0139     cout << PHWHERE << "Wrong pixel value X= " << Ngridx << " and Z= " << Ngridz << endl;
0140   }
0141 
0142   // numbering starts at zero
0143   return Ngridx + Ngridz * get_NX();
0144 }
0145 
0146 TVector3 CylinderGeom_Mvtx::get_local_coords_from_pixel(int NXZ)
0147 {
0148   int Ngridz = NXZ / get_NX();
0149   int Ngridx = NXZ % get_NX();
0150 
0151   return get_local_coords_from_pixel(Ngridx, Ngridz);
0152 }
0153 
0154 TVector3 CylinderGeom_Mvtx::get_local_coords_from_pixel(int iRow, int iCol)
0155 {
0156   TVector3 local;
0157   bool check = SegmentationAlpide::detectorToLocal((float) iRow, (float) iCol, local);
0158   if (!check)
0159   {
0160     cout << PHWHERE << "Pixel coord ( " << iRow << ", " << iCol << " )"
0161          << "out of range" << endl;
0162   }
0163   // Transform location in chip to location in sensors
0164   TVector3 trChipToSens(loc_sensor_in_chip[0],
0165                         loc_sensor_in_chip[1],
0166                         loc_sensor_in_chip[2]);
0167   local -= trChipToSens;
0168   return local;
0169 }
0170 
0171 void CylinderGeom_Mvtx::identify(std::ostream& os) const
0172 {
0173   os << "CylinderGeom_Mvtx: layer: " << layer
0174      << ", layer_radius: " << layer_radius
0175      << ", N_staves in layer: " << N_staves
0176      << ", N_half_staves in layer: " << N_half_staves
0177      << ", pixel_x: " << pixel_x
0178      << ", pixel_z: " << pixel_z
0179      << ", pixel_thickness: " << pixel_thickness
0180      << endl;
0181   return;
0182 }
0183 
0184 // hide SegmentationAlpide include from root5 rootcint (rootcling is fine)
0185 int CylinderGeom_Mvtx::get_NZ() const
0186 {
0187   return SegmentationAlpide::NCols;
0188 }
0189 
0190 int CylinderGeom_Mvtx::get_NX() const
0191 {
0192   return SegmentationAlpide::NRows;
0193 }
0194 
0195 int CylinderGeom_Mvtx::get_pixel_X_from_pixel_number(int NXZ)
0196 {
0197   return NXZ % get_NX();
0198 }
0199 
0200 int CylinderGeom_Mvtx::get_pixel_Z_from_pixel_number(int NXZ)
0201 {
0202   return NXZ / get_NX();
0203 }
0204 
0205 int CylinderGeom_Mvtx::get_pixel_number_from_xbin_zbin(int xbin, int zbin)  // obsolete
0206 {
0207   return xbin + zbin * get_NX();
0208 }