Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CylinderGeomMicromegas.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file CylinderGeomMicromegas.cc
1 
7 
8 #include <g4main/PHG4Hit.h>
10 
13 #include <TVector3.h>
14 
15 #include <cassert>
16 
17 namespace
18 {
19  // convenient square function
20  template<class T>
21  inline constexpr T square( const T& x ) { return x*x; }
22 
24  template<class T>
25  inline constexpr T get_r( T x, T y ) { return std::sqrt( square(x) + square(y) ); }
26 
27  // bind angle to [-M_PI,+M_PI[. This is useful to avoid edge effects when making the difference between two angles
28  template<class T>
29  inline T bind_angle( const T& angle )
30  {
31  if( angle >= M_PI ) return angle - 2*M_PI;
32  else if( angle < -M_PI ) return angle + 2*M_PI;
33  else return angle;
34  }
35 
36 }
37 
38 //________________________________________________________________________________
39 TVector3 CylinderGeomMicromegas::get_local_from_world_coords( uint tileid, ActsGeometry* geometry, const TVector3& world_coordinates ) const
40 {
41  assert( tileid < m_tiles.size() );
43  const auto surface = geometry->maps().getMMSurface(hitsetkey);
44 
45  const Acts::Vector3 global(
46  world_coordinates.x()*Acts::UnitConstants::cm,
47  world_coordinates.y()*Acts::UnitConstants::cm,
48  world_coordinates.z()*Acts::UnitConstants::cm );
49 
50  // convert to local
51  /* this is equivalent to calling surface->globalToLocal but without the "on surface" check, and while returning a full Acts::Vector3 */
52  const auto local = surface->transform(geometry->geometry().getGeoContext()).inverse()*global;
53  return TVector3(
54  local.x()/Acts::UnitConstants::cm,
55  local.y()/Acts::UnitConstants::cm,
56  local.z()/Acts::UnitConstants::cm );
57 }
58 
59 //________________________________________________________________________________
60 TVector3 CylinderGeomMicromegas::get_local_from_world_vect( uint tileid, ActsGeometry* geometry, const TVector3& world_vect ) const
61 {
62  assert( tileid < m_tiles.size() );
64  const auto surface = geometry->maps().getMMSurface(hitsetkey);
65 
66  const Acts::Vector3 global(
67  world_vect.x()*Acts::UnitConstants::cm,
68  world_vect.y()*Acts::UnitConstants::cm,
69  world_vect.z()*Acts::UnitConstants::cm );
70 
71  const Acts::Vector3 local = surface->referenceFrame(geometry->geometry().getGeoContext(), Acts::Vector3(), Acts::Vector3()).inverse()*global;
72  return TVector3(
73  local.x()/Acts::UnitConstants::cm,
74  local.y()/Acts::UnitConstants::cm,
75  local.z()/Acts::UnitConstants::cm );
76 }
77 
78 //________________________________________________________________________________
79 TVector3 CylinderGeomMicromegas::get_world_from_local_coords( uint tileid, ActsGeometry* geometry, const TVector2& local_coordinates ) const
80 {
81  assert( tileid < m_tiles.size() );
83  const auto surface = geometry->maps().getMMSurface(hitsetkey);
84 
85  const Acts::Vector2 local(
86  local_coordinates.X()*Acts::UnitConstants::cm,
87  local_coordinates.Y()*Acts::UnitConstants::cm );
88 
89  // convert to global
90  const auto global = surface->localToGlobal(geometry->geometry().getGeoContext(), local, Acts::Vector3());
91  return TVector3(
92  global.x()/Acts::UnitConstants::cm,
93  global.y()/Acts::UnitConstants::cm,
94  global.z()/Acts::UnitConstants::cm );
95 }
96 
97 //________________________________________________________________________________
98 TVector3 CylinderGeomMicromegas::get_world_from_local_coords( uint tileid, ActsGeometry* geometry, const TVector3& local_coordinates ) const
99 {
100  assert( tileid < m_tiles.size() );
102  const auto surface = geometry->maps().getMMSurface(hitsetkey);
103 
104  const Acts::Vector3 local(
105  local_coordinates.x()*Acts::UnitConstants::cm,
106  local_coordinates.y()*Acts::UnitConstants::cm,
107  local_coordinates.z()*Acts::UnitConstants::cm );
108 
109  // convert to global
110  /* this is equivalent to calling surface->localToGlobal but without assuming that the local point is on surface */
111  const auto global = surface->transform(geometry->geometry().getGeoContext())*local;
112  return TVector3(
113  global.x()/Acts::UnitConstants::cm,
114  global.y()/Acts::UnitConstants::cm,
115  global.z()/Acts::UnitConstants::cm );
116 }
117 
118 //________________________________________________________________________________
119 TVector3 CylinderGeomMicromegas::get_world_from_local_vect( uint tileid, ActsGeometry* geometry, const TVector3& local_vect ) const
120 {
121  assert( tileid < m_tiles.size() );
123  const auto surface = geometry->maps().getMMSurface(hitsetkey);
124 
125  Acts::Vector3 local(
126  local_vect.x()*Acts::UnitConstants::cm,
127  local_vect.y()*Acts::UnitConstants::cm,
128  local_vect.z()*Acts::UnitConstants::cm );
129 
130  const Acts::Vector3 global = surface->referenceFrame(geometry->geometry().getGeoContext(), Acts::Vector3(), Acts::Vector3())*local;
131  return TVector3(
132  global.x()/Acts::UnitConstants::cm,
133  global.y()/Acts::UnitConstants::cm,
134  global.z()/Acts::UnitConstants::cm );
135 }
136 
137 //________________________________________________________________________________
138 int CylinderGeomMicromegas::find_tile_cylindrical( const TVector3& world_coordinates ) const
139 {
140  // convert to polar coordinates
141  const auto phi = std::atan2( world_coordinates.y(), world_coordinates.x() );
142  const auto z = world_coordinates.z();
143 
144  for( size_t itile = 0; itile < m_tiles.size(); ++itile )
145  {
146  const auto& tile = m_tiles.at(itile);
147 
148  if( std::abs( z - tile.m_centerZ ) > tile.m_sizeZ/2 ) continue;
149  if( std::abs( bind_angle( phi - tile.m_centerPhi ) ) > tile.m_sizePhi/2 ) continue;
150 
151  return itile;
152  }
153 
154  return -1;
155 }
156 
157 //________________________________________________________________________________
158 int CylinderGeomMicromegas::find_strip_from_world_coords( uint tileid, ActsGeometry* geometry, const TVector3& world_coordinates ) const
159 {
160  // convert to local coordinates
161  const auto local_coordinates = get_local_from_world_coords( tileid, geometry, world_coordinates );
162 
163  // check against thickness
164  if( std::abs(local_coordinates.z() ) >= m_thickness/2 )
165  {
166  std::cout << " CylinderGeomMicromegas::find_strip_from_world_coords - invalid world coordinates" << std::endl;
167  return -1;
168  } else {
169  return find_strip_from_local_coords( tileid, geometry, { local_coordinates.x(), local_coordinates.y() } );
170  }
171 }
172 
173 //________________________________________________________________________________
174 int CylinderGeomMicromegas::find_strip_from_local_coords( uint tileid, ActsGeometry* geometry, const TVector2& local_coordinates ) const
175 {
176  assert( tileid < m_tiles.size() );
178  const auto surface = geometry->maps().getMMSurface(hitsetkey);
179 
180  // get boundaries and corresponding dimension
181  assert( surface->bounds().type() == Acts::SurfaceBounds::BoundsType::eRectangle );
182  auto rectangle_bounds = static_cast<const Acts::RectangleBounds*>( &surface->bounds() );
183  const auto half_length_x = rectangle_bounds->halfLengthX()/Acts::UnitConstants::cm;
184  const auto half_length_y = rectangle_bounds->halfLengthY()/Acts::UnitConstants::cm;
185 
186  // check azimuth
187  if( std::abs( local_coordinates.X() ) > half_length_x ) return -1;
188 
189  // check z extend
190  if( std::abs( local_coordinates.Y() ) > half_length_y ) return -1;
191 
192  // calculate strip index, depending on segmentation
193  switch( m_segmentation_type )
194  {
196  return (int) std::floor((local_coordinates.X() + half_length_x)/m_pitch);
197 
199  return (int) std::floor((local_coordinates.Y() + half_length_y)/m_pitch);
200  }
201 
202  // unreachable
203  return -1;
204 }
205 
206 //________________________________________________________________________________
208 {
209  assert( tileid < m_tiles.size() );
211  const auto surface = geometry->maps().getMMSurface(hitsetkey);
212 
213  // get boundaries and return corresponding dimension
214  assert( surface->bounds().type() == Acts::SurfaceBounds::BoundsType::eRectangle );
215  auto rectangle_bounds = static_cast<const Acts::RectangleBounds*>( &surface->bounds() );
216  switch( m_segmentation_type )
217  {
219  return 2.*rectangle_bounds->halfLengthY()/Acts::UnitConstants::cm;
220 
222  return 2.*rectangle_bounds->halfLengthX()/Acts::UnitConstants::cm;
223  }
224 
225  // unreachable
226  return 0;
227 }
228 
229 //________________________________________________________________________________
231 {
232  assert( tileid < m_tiles.size() );
234  const auto surface = geometry->maps().getMMSurface(hitsetkey);
235 
236  // get boundaries and corresponding dimension
237  assert( surface->bounds().type() == Acts::SurfaceBounds::BoundsType::eRectangle );
238  auto rectangle_bounds = static_cast<const Acts::RectangleBounds*>( &surface->bounds() );
239  switch( m_segmentation_type )
240  {
242  return std::floor( (2.*rectangle_bounds->halfLengthX()/Acts::UnitConstants::cm)/m_pitch );
243 
245  return std::floor( (2.*rectangle_bounds->halfLengthY()/Acts::UnitConstants::cm)/m_pitch );
246  }
247 
248  // unreachable
249  return 0;
250 }
251 
252 //________________________________________________________________________________
253 TVector2 CylinderGeomMicromegas::get_local_coordinates( uint tileid, ActsGeometry* geometry, uint stripnum ) const
254 {
255  assert( tileid < m_tiles.size() );
257  const auto surface = geometry->maps().getMMSurface(hitsetkey);
258 
259  // get boundaries and return corresponding dimension
260  assert( surface->bounds().type() == Acts::SurfaceBounds::BoundsType::eRectangle );
261  auto rectangle_bounds = static_cast<const Acts::RectangleBounds*>( &surface->bounds() );
262 
263  switch( m_segmentation_type )
264  {
266  return TVector2( (0.5+stripnum)*m_pitch-rectangle_bounds->halfLengthX()/Acts::UnitConstants::cm, 0 );
267 
269  return TVector2( 0, (0.5+stripnum)*m_pitch-rectangle_bounds->halfLengthY()/Acts::UnitConstants::cm );
270  }
271 
272  // unreachable
273  return TVector2();
274 }
275 
276 //________________________________________________________________________________
277 TVector3 CylinderGeomMicromegas::get_world_coordinates( uint tileid, ActsGeometry* geometry, uint stripnum ) const
278 { return get_world_from_local_coords( tileid, geometry, get_local_coordinates( tileid, geometry, stripnum ) ); }
279 
280 //________________________________________________________________________________
281 void CylinderGeomMicromegas::identify( std::ostream& out ) const
282 {
283  out << "CylinderGeomMicromegas" << std::endl;
284  out << "layer: " << m_layer << std::endl;
285  out << "segmentation_type: " << (m_segmentation_type == MicromegasDefs::SegmentationType::SEGMENTATION_PHI ? "SEGMENTATION_PHI":"SEGMENTATION_Z") << std::endl;
286  out << "drift_direction: " << (m_drift_direction == MicromegasDefs::DriftDirection::INWARD ? "INWARD":"OUTWARD") << std::endl;
287  out << "radius: " << m_radius << "cm" << std::endl;
288  out << "thickness: " << m_thickness << "cm" << std::endl;
289  out << "zmin: " << m_zmin << "cm" << std::endl;
290  out << "zmax: " << m_zmax << "cm" << std::endl;
291  out << "pitch: " << m_pitch << "cm" << std::endl;
292  out << std::endl;
293 }
294 
295 //________________________________________________________________________________
296 bool CylinderGeomMicromegas::check_radius( const TVector3& world_coordinates ) const
297 {
298  const auto radius = get_r( world_coordinates.x(), world_coordinates.y() );
299  return std::abs( radius - m_radius ) <= m_thickness/2;
300 }