ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PHTpcDeltaZCorrection.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file PHTpcDeltaZCorrection.cc
2 
4 
6 
7 #include <trackbase/TrkrCluster.h> // for TrkrCluster
9 #include <trackbase_historic/SvtxTrack.h> // for SvtxTrack, SvtxTrack::C...
11 
13 
14 #include <phool/getClass.h>
15 #include <phool/phool.h>
16 
17 #include <gsl/gsl_const_mksa.h> // for the speed of light
18 #include <cmath> // for sqrt, fabs, atan2, cos
19 #include <iostream> // for operator<<, basic_ostream
20 #include <map> // for map
21 #include <set> // for _Rb_tree_const_iterator
22 #include <utility> // for pair, make_pair
23 
24 namespace
25 {
27  template<class T> inline constexpr T square( const T& x ) { return x*x; }
28 
30  static constexpr double speed_of_light = GSL_CONST_MKSA_SPEED_OF_LIGHT*1e-7;
31 
32 }
33 
34 //____________________________________________________________________________..
36  : SubsysReco(name)
37  , PHParameterInterface(name)
39 
40 
41 //____________________________________________________________________________..
43 {
45  m_drift_velocity = get_double_param("drift_velocity");
46  m_bz_const = get_double_param("bz_const");
48 }
49 
50 //____________________________________________________________________________..
52 {
53  // load nodes
54  const auto res = load_nodes(topNode);
55  if( res != Fun4AllReturnCodes::EVENT_OK ) return res;
56 
59 }
60 
61 //_____________________________________________________________________
64 
65 //_____________________________________________________________________
67 {
68  // Data on gasses @20 C and 760 Torr from the following source:
69  // http://www.slac.stanford.edu/pubs/icfa/summer98/paper3/paper3.pdf
70  // diffusion and drift velocity for 400kV for NeCF4 50/50 from calculations:
71  // http://skipper.physics.sunysb.edu/~prakhar/tpc/HTML_Gases/split.html
72  set_default_double_param("drift_velocity", 8.0 / 1000.0); // cm/ns
73  set_default_double_param("bz_const", 1.4); // Tesla
74  return;
75 }
76 
77 //_____________________________________________________________________
79 {
80 
81  // acts surface map
82  m_surfmaps = findNode::getClass<ActsSurfaceMaps>(topNode, "ActsSurfaceMaps");
83  assert( m_surfmaps );
84 
85  // acts geometry
86  m_tGeometry = findNode::getClass<ActsTrackingGeometry>(topNode, "ActsTrackingGeometry");
87  assert( m_tGeometry );
88 
89  // get necessary nodes
90  m_track_map = findNode::getClass<SvtxTrackMap>(topNode, "SvtxTrackMap");
91  assert(m_track_map);
92 
93  m_cluster_map = findNode::getClass<TrkrClusterContainer>(topNode, "CORRECTED_TRKR_CLUSTER");
94  if(m_cluster_map)
95  {
96  if(Verbosity() > 0) std::cout << " Using CORRECTED_TRKR_CLUSTER node " << std::endl;
97  }
98  else
99  {
100  if(Verbosity() > 0) std::cout << " CORRECTED_TRKR_CLUSTER node not found, using TRKR_CLUSTER" << std::endl;
101  m_cluster_map = findNode::getClass<TrkrClusterContainer>(topNode, "TRKR_CLUSTER");
102  }
103  assert(m_cluster_map);
105 }
106 
107 //_____________________________________________________________________
109 {
110  if( !( m_track_map && m_cluster_map ) ) return;
111  for( auto iter = m_track_map->begin(); iter != m_track_map->end(); ++iter )
112  { process_track( iter->first, iter->second ); }
113 
114  m_corrected_clusters.clear();
115 }
116 
117 //_____________________________________________________________________
119 {
120 
121  // keep track of the global position of previous cluster on track
122  const Acts::Vector3D origin = {track->get_x(), track->get_y(), track->get_z()};
123 
124  // pt
125  const double pt = std::sqrt(square(track->get_px())+square(track->get_py()));
126 
127  // radius
128  const double radius = (pt/(0.3*m_bz_const))*1e2; // cm
129 
130  // helix center
131  const double center_x = (track->get_positive_charge() ? origin.x()+radius*track->get_py():origin.x()-radius*track->get_py())/pt;
132  const double center_y = (track->get_positive_charge() ? origin.y()-radius*track->get_px():origin.y()+radius*track->get_px())/pt;
133 
134  // origin to center 2D vector
135  const Acts::Vector2D orig_vect = {origin.x()-center_x, origin.y()-center_y };
136 
137  // print
138  if( Verbosity() )
139  {
140  std::cout << "PHTpcDeltaZCorrection -"
141  << " track: " << key
142  << " positive: " << track->get_positive_charge()
143  << " center: " << center_x << ", " << center_y
144  << " radius: " << radius
145  << std::endl;
146  }
147 
148  // loop over clusters. Assume they are ordered by layer
149  for( auto key_iter = track->begin_cluster_keys(); key_iter != track->end_cluster_keys(); ++key_iter)
150  {
151  // store cluster key
152  const auto& cluster_key = *key_iter;
153 
154  // consider TPC clusters only
155  if( TrkrDefs::getTrkrId(cluster_key) != TrkrDefs::tpcId ) continue;
156 
157  // skip if cluster was already corrected
158  if( !m_corrected_clusters.insert(cluster_key).second ) continue;
159 
160  // get cluster
161  auto cluster = m_cluster_map->findCluster( cluster_key );
162  if(!cluster) continue;
163 
164  // get cluster global position
165  const auto global = m_transformer.getGlobalPosition(cluster,m_surfmaps, m_tGeometry);
166 
167  // get delta z
168  const double delta_z = global.z() - origin.z();
169 
170  // cluster position to center
171  const Acts::Vector2D cluster_vect = {global.x()-center_x, global.y()-center_y};
172 
173  // delta phi
174  const double delta_phi = std::atan2(
175  cluster_vect.y()*orig_vect.x()-cluster_vect.x()*orig_vect.y(),
176  cluster_vect.x()*orig_vect.x() + cluster_vect.y()*orig_vect.y() );
177 
178  // helical path length
179  const double pathlength = std::sqrt( square( delta_z ) + square( radius*delta_phi ) );
180  if( Verbosity() )
181  { std::cout << "PHTpcDeltaZCorrection::process_track - cluster: " << cluster_key << " path length: " << pathlength << std::endl; }
182 
183  // adjust cluster position to account for particles propagation time
184  /*
185  * accounting for particles finite velocity results in reducing the electron drift time by pathlenght/c
186  * this in turn affects the cluster z, so that it is always closer to the readout plane
187  */
188  const double z_correction = pathlength * m_drift_velocity/speed_of_light;
189  if( global.z() > 0 ) cluster->setLocalY( cluster->getLocalY()+z_correction);
190  else cluster->setLocalY( cluster->getLocalY()-z_correction);
191 
192  }
193 
194 }