LDMX Software
tracking::sim::SeedToTrackParamMaker Class Reference

Public Member Functions

template<typename external_spacepoint_t >
bool karimakiFit (const std::vector< external_spacepoint_t * > &sp, std::array< double, 9 > &data, const Acts::Vector2 refPoint)
 
bool transformRhoPhid (const Acts::Vector2 &r1, const Acts::Vector2 &r2, double &phi, double &rho, double &d)
 
template<typename external_spacepoint_t >
bool fitSeedAtlas (const std::vector< external_spacepoint_t > &sp, std::array< double, 9 > &data, const Acts::Transform3 &Tp, const double &bFieldZ)
 This resembles the method used in ATLAS for the seed fitting L811 https://acode-browser.usatlas.bnl.gov/lxr/source/athena/InnerDetector/InDetRecTools/SiTrackMakerTool_xk/src/SiTrackMaker_xk.cxx.
 
template<typename spacepoint_iterator_t >
std::optional< Acts::BoundVector > estimateTrackParamsFromSeed (const Acts::Transform3 &Tp, spacepoint_iterator_t spBegin, spacepoint_iterator_t spEnd, Acts::Vector3 bField, double bFieldMin, double mass=139.57018 *Acts::UnitConstants::MeV)
 This is a simple Line and Parabola fit (from HPS reconstruction by Robert Johnson)
 

Detailed Description

Definition at line 14 of file SeedToTrackParamMaker.h.

Constructor & Destructor Documentation

◆ SeedToTrackParamMaker()

tracking::sim::SeedToTrackParamMaker::SeedToTrackParamMaker ( )
inline

Definition at line 16 of file SeedToTrackParamMaker.h.

16{};

Member Function Documentation

◆ estimateTrackParamsFromSeed()

template<typename spacepoint_iterator_t >
std::optional< Acts::BoundVector > tracking::sim::SeedToTrackParamMaker::estimateTrackParamsFromSeed ( const Acts::Transform3 & Tp,
spacepoint_iterator_t spBegin,
spacepoint_iterator_t spEnd,
Acts::Vector3 bField,
double bFieldMin,
double mass = 139.57018 * Acts::UnitConstants::MeV )
inline

This is a simple Line and Parabola fit (from HPS reconstruction by Robert Johnson)

Estimate the full track parameters from three space points

This method is based on the conformal map transformation. It estimates the full bound track parameters, i.e. (loc0, loc1, phi, theta, q/p, t) at the bottom space point. The bottom space is assumed to be the first element in the range defined by the iterators. The magnetic field (which might be along any direction) is also necessary for the momentum estimation.

It resembles the method used in ATLAS for the track parameters estimated from seed, i.e. the function InDet::SiTrackMaker_xk::getAtaPlane here: https://acode-browser.usatlas.bnl.gov/lxr/source/athena/InnerDetector/InDetRecTools/SiTrackMakerTool_xk/src/SiTrackMaker_xk.cxx

Template Parameters
spacepoint_iterator_tThe type of space point iterator
Parameters
tpthe local to global transformation
spBeginis the begin iterator for the space points
spEndis the end iterator for the space points
surfaceis the surface of the bottom space point. The estimated bound track parameters will be represented also at this surface
bFieldis the magnetic field vector
bFieldMinis the minimum magnetic field required to trigger the estimation of q/pt
massis the estimated particle mass
Returns
optional bound parameters

Definition at line 93 of file SeedToTrackParamMaker.h.

96 {
97 // Check the number of provided space points
98 size_t num_sp = std::distance(spBegin, spEnd);
99 if (num_sp != 3) {
100 std::cout << "ERROR::less than 3 point provided" << std::endl;
101 return std::nullopt;
102 }
103
104 // Convert bField to Tesla
105 double b_field_in_tesla = bField.norm() / Acts::UnitConstants::T;
106 double b_field_min_in_tesla = bFieldMin / Acts::UnitConstants::T;
107 // Check if magnetic field is too small
108 if (b_field_in_tesla < b_field_min_in_tesla) {
109 // @todo shall we use straight-line estimation and use default q/pt in
110 // such case?
111 std::cout << "The magnetic field at the bottom space point: B = "
112 << b_field_in_tesla
113 << " T is smaller than |B|_min = " << b_field_min_in_tesla
114 << " T. Estimation is not performed." << std::endl;
115 return std::nullopt;
116 }
117
118 // The global positions of the bottom, middle and space points
119 std::array<Acts::Vector3, 3> sp_global_positions = {
120 Acts::Vector3::Zero(), Acts::Vector3::Zero(), Acts::Vector3::Zero()};
121 // The first, second and third space point are assumed to be bottom, middle
122 // and top space point, respectively
123 for (size_t isp = 0; isp < 3; ++isp) {
124 spacepoint_iterator_t it = std::next(spBegin, isp);
125 if (*it == nullptr) {
126 std::cout << "Empty space point found. This should not happen."
127 << std::endl;
128 return std::nullopt;
129 }
130 const auto& sp = *it;
131 sp_global_positions[isp] = Acts::Vector3(sp->x(), sp->y(), sp->z());
132 }
133
134 // Define a new coordinate frame with its origin at the bottom space point,
135 // z_ axis along the magnetic field direction and y_ axis perpendicular to
136 // vector from the bottom to middle space point. Hence, the projection of
137 // the middle space point on the tranverse plane will be located at the x_
138 // axis of the new frame.
139 Acts::Vector3 rel_vec = sp_global_positions[1] - sp_global_positions[0];
140 Acts::Vector3 new_z_axis = bField.normalized();
141 Acts::Vector3 new_y_axis = new_z_axis.cross(rel_vec).normalized();
142 Acts::Vector3 new_x_axis = new_y_axis.cross(new_z_axis);
143 Acts::RotationMatrix3 rotation;
144 rotation.col(0) = new_x_axis;
145 rotation.col(1) = new_y_axis;
146 rotation.col(2) = new_z_axis;
147 // The center of the new frame is at the bottom space point
148 Acts::Translation3 trans(sp_global_positions[0]);
149 // The transform which constructs the new frame
150 Acts::Transform3 transform(trans * rotation);
151
152 // The coordinate of the middle and top space point in the new frame
153 Acts::Vector3 local1 = transform.inverse() * sp_global_positions[1];
154 Acts::Vector3 local2 = transform.inverse() * sp_global_positions[2];
155
156 // Lambda to transform the coordinates to the (u, v) space
157 auto uv_transform = [](const Acts::Vector3& local) -> Acts::Vector2 {
158 Acts::Vector2 uv;
159 double denominator = local.x() * local.x() + local.y() * local.y();
160 uv.x() = local.x() / denominator;
161 uv.y() = local.y() / denominator;
162 return uv;
163 };
164 // The uv1.y() should be zero
165 Acts::Vector2 uv1 = uv_transform(local1);
166 Acts::Vector2 uv2 = uv_transform(local2);
167
168 // A,B are slope and intercept of the straight line in the u,v plane
169 // connecting the three points
170 double a = (uv2.y() - uv1.y()) / (uv2.x() - uv1.x());
171 double b = uv2.y() - a * uv2.x();
172 // Curvature (with a sign) estimate
173 double rho = -2.0 * b / std::hypot(1., a);
174 // The projection of the top space point on the transverse plane of the new
175 // frame
176 double rn = local2.x() * local2.x() + local2.y() * local2.y();
177 // The (1/tanTheta) of momentum in the new frame,
178 double inv_tan_theta =
179 local2.z() * std::sqrt(1. / rn) / (1. + rho * rho * rn);
180 // The momentum direction in the new frame (the center of the circle has the
181 // coordinate (-1.*A/(2*B), 1./(2*B)))
182 Acts::Vector3 trans_direction(1., a, std::hypot(1, a) * inv_tan_theta);
183 // Transform it back to the original frame
184 [[maybe_unused]] Acts::Vector3 direction =
185 rotation * trans_direction.normalized();
186
187 // Initialize the bound parameters vector
188 Acts::BoundVector params = Acts::BoundVector::Zero();
189
190 // The estimated phi and theta
191 // params[Acts::eBoundPhi] = Acts::VectorHelpers::phi(direction);
192 // params[Acts::eBoundTheta] = Acts::VectorHelpers::theta(direction);
193
194 Acts::Vector3 bottom_local_pos = Tp.inverse() * sp_global_positions[0];
195
196 // The estimated loc0 and loc1
197 params[Acts::eBoundLoc0] = bottom_local_pos.x();
198 params[Acts::eBoundLoc1] = bottom_local_pos.y();
199
200 // The estimated q/pt in [GeV/c]^-1 (note that the pt is the projection of
201 // momentum on the transverse plane of the new frame)
202 double q_over_pt =
203 rho * (Acts::UnitConstants::m) / (0.3 * b_field_in_tesla);
204 // The estimated q/p in [GeV/c]^-1
205 params[Acts::eBoundQOverP] = q_over_pt / std::hypot(1., inv_tan_theta);
206
207 // The estimated momentum, and its projection along the magnetic field
208 // diretion
209 double p_in_ge_v = std::abs(1.0 / params[Acts::eBoundQOverP]);
210 double pz_in_ge_v = 1.0 / std::abs(q_over_pt) * inv_tan_theta;
211 double mass_in_ge_v = mass / Acts::UnitConstants::GeV;
212 // The estimated velocity, and its projection along the magnetic field
213 // diretion
214 double v = p_in_ge_v / std::hypot(p_in_ge_v, mass_in_ge_v);
215 double vz = pz_in_ge_v / std::hypot(p_in_ge_v, mass_in_ge_v);
216 // The z_ coordinate of the bottom space point along the magnetic field
217 // direction
218 double pathz = sp_global_positions[0].dot(bField) / bField.norm();
219 // The estimated time (use path length along magnetic field only if it's not
220 // zero)
221 if (pathz != 0) {
222 params[Acts::eBoundTime] = pathz / vz;
223 } else {
224 params[Acts::eBoundTime] = sp_global_positions[0].norm() / v;
225 }
226
227 return params;
228 }

◆ transformRhoPhid()

bool tracking::sim::SeedToTrackParamMaker::transformRhoPhid ( const Acts::Vector2 & r1,
const Acts::Vector2 & r2,
double & phi,
double & rho,
double & d )
inline

Definition at line 28 of file SeedToTrackParamMaker.h.

29 {
30 float track_dir = cos(phi) * (r1[0] - r2[0]) + sin(phi) * (r1[1] - r2[1]);
31
32 if (track_dir < 0) {
33 phi = M_PI + phi;
34 rho = -rho;
35 d = -d;
36 return true;
37 }
38
39 else
40 return false;
41 }

The documentation for this class was generated from the following file: