Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-12-17 09:20:48

0001 /*!
0002  * \file TrackSeedHelper.cc
0003  * \author Hugo Pereira Da Costa <hugo.pereira-da-costa@lanl.gov>
0004  */
0005 
0006 #include "TrackSeedHelper.h"
0007 #include "TrackSeed.h"
0008 
0009 #include <trackbase/TrackFitUtils.h>
0010 
0011 namespace
0012 {
0013 
0014   //! convenience square method
0015   template <class T>
0016   inline constexpr T square(const T& x)
0017   {
0018     return x * x;
0019   }
0020 }
0021   std::pair<float, float> TrackSeedHelper::findRoot(const float& qOverR, const float& X0, const float& Y0)
0022   {
0023     /**
0024     * We need to determine the closest point on the circle to the origin
0025     * since we can't assume that the track originates from the origin
0026     * The eqn for the circle is (x-X0)^2+(y-Y0)^2=R^2 and we want to
0027     * minimize d = sqrt((0-x)^2+(0-y)^2), the distance between the
0028     * origin and some (currently, unknown) point on the circle x,y.
0029     *
0030     * Solving the circle eqn for x and substituting into d gives an eqn for
0031     * y. Taking the derivative and setting equal to 0 gives the following
0032     * two solutions. We take the smaller solution as the correct one, as
0033     * usually one solution is wildly incorrect (e.g. 1000 cm)
0034     */
0035     const float R = std::abs(1./qOverR);
0036     const double miny = (std::sqrt(square(X0) * square(R) * square(Y0) + square(R) * pow(Y0, 4)) + square(X0) * Y0 + pow(Y0, 3)) / (square(X0) + square(Y0));
0037     const double miny2 = (-std::sqrt(square(X0) * square(R) * square(Y0) + square(R) * pow(Y0, 4)) + square(X0) * Y0 + pow(Y0, 3)) / (square(X0) + square(Y0));
0038 
0039     const double minx = std::sqrt(square(R) - square(miny - Y0)) + X0;
0040     const double minx2 = -std::sqrt(square(R) - square(miny2 - Y0)) + X0;
0041 
0042     /// Figure out which of the two roots is actually closer to the origin
0043     const float x = (std::abs(minx) < std::abs(minx2)) ? minx : minx2;
0044     const float y = (std::abs(miny) < std::abs(miny2)) ? miny : miny2;
0045     return {x, y};
0046   }
0047   std::pair<float, float> TrackSeedHelper::findRoot(TrackSeed const* seed)
0048   {
0049     return findRoot(seed->get_qOverR(), seed->get_X0(), seed->get_Y0());
0050   }
0051 
0052 
0053 
0054 //____________________________________________________________________________________
0055 float TrackSeedHelper::get_phi(TrackSeed const* seed, const TrackSeedHelper::position_map_t& positions)
0056 {
0057   const auto X0 = seed->get_X0();
0058   const auto Y0 = seed->get_Y0();
0059   const auto [x, y] = findRoot(seed);
0060 
0061   // This is the angle of the tangent to the circle
0062   // The argument is the slope of the tangent (inverse of slope of radial line at tangent)
0063   float phi = std::atan2(-1 * (X0 - x), (Y0 - y));
0064   Acts::Vector3 pos0 = positions.find(*(seed->begin_cluster_keys()))->second;
0065   Acts::Vector3 pos1 = positions.find(*std::next(seed->begin_cluster_keys()))->second;
0066 
0067   // we need to know if the track proceeds clockwise or CCW around the circle
0068   double dx0 = pos0(0) - X0;
0069   double dy0 = pos0(1) - Y0;
0070   double phi0 = std::atan2(dy0, dx0);
0071   double dx1 = pos1(0) - X0;
0072   double dy1 = pos1(1) - Y0;
0073   double phi1 = std::atan2(dy1, dx1);
0074   double dphi = phi1 - phi0;
0075 
0076   // need to deal with the switch from -pi to +pi at phi = 180 degrees
0077   // final phi - initial phi must be < 180 degrees for it to be a valid track
0078   if (dphi > M_PI)
0079   {
0080     dphi -= 2.0 * M_PI;
0081   }
0082   if (dphi < -M_PI)
0083   {
0084     dphi += M_PI;
0085   }
0086 
0087   // whether we add 180 degrees depends on the angle of the bend
0088   if (dphi < 0)
0089   {
0090     phi += M_PI;
0091     if (phi > M_PI)
0092     {
0093       phi -= 2. * M_PI;
0094     }
0095   }
0096 
0097   return phi;
0098 }
0099 
0100 //____________________________________________________________________________________
0101 float TrackSeedHelper::get_phi_fastsim(TrackSeed const* seed)
0102 {
0103   const auto [x, y] = findRoot(seed);
0104   return std::atan2(-(seed->get_X0()-x), (seed->get_Y0() - y));
0105 }
0106 
0107 //____________________________________________________________________________________
0108 void TrackSeedHelper::circleFitByTaubin(
0109   TrackSeed* seed,
0110   const TrackSeedHelper::position_map_t& positions,
0111   uint8_t startLayer,
0112   uint8_t endLayer)
0113 {
0114   TrackFitUtils::position_vector_t positions_2d;
0115   for( auto key_iter = seed->begin_cluster_keys(); key_iter != seed->end_cluster_keys(); ++key_iter )
0116   {
0117     const auto& key(*key_iter);
0118     const auto layer = TrkrDefs::getLayer(key);
0119     if (layer < startLayer || layer > endLayer)
0120     {
0121       continue;
0122     }
0123 
0124     const auto iter = positions.find(key);
0125 
0126     /// you supplied the wrong key...
0127     if (iter == positions.end())
0128     {
0129       continue;
0130     }
0131 
0132     // add to 2d position list
0133     const Acts::Vector3& pos = iter->second;
0134     positions_2d.emplace_back(pos.x(), pos.y());
0135   }
0136 
0137   // cannot fit if there is less than 3 positions
0138   if( positions_2d.size() < 3 ) { return; }
0139 
0140   // do the fit
0141   const auto [r, x0, y0] = TrackFitUtils::circle_fit_by_taubin(positions_2d);
0142   float qOverR = 1./r;
0143 
0144   /// Set the charge
0145   const auto& firstpos = positions_2d.at(0);
0146   const auto& secondpos = positions_2d.at(1);
0147 
0148   const auto firstphi = atan2(firstpos.second, firstpos.first);
0149   const auto secondphi = atan2(secondpos.second, secondpos.first);
0150   auto dphi = secondphi - firstphi;
0151   if (dphi > M_PI)
0152   {
0153     dphi = 2.*M_PI-dphi;
0154   }
0155 
0156   if (dphi < -M_PI)
0157   {
0158     dphi = 2*M_PI + dphi;
0159   }
0160   if (dphi > 0)
0161   {
0162     qOverR *= -1;
0163   }
0164 
0165   // assign
0166   seed->set_X0(x0);
0167   seed->set_Y0(y0);
0168   seed->set_qOverR(qOverR);
0169 }
0170 
0171 //____________________________________________________________________________________
0172 void TrackSeedHelper::lineFit(
0173   TrackSeed* seed,
0174   const TrackSeedHelper::position_map_t& positions,
0175   uint8_t startLayer,
0176   uint8_t endLayer)
0177 {
0178   TrackFitUtils::position_vector_t positions_2d;
0179   for( auto key_iter = seed->begin_cluster_keys(); key_iter != seed->end_cluster_keys(); ++key_iter )
0180   {
0181     const auto& key(*key_iter);
0182     const auto layer = TrkrDefs::getLayer(key);
0183     if (layer < startLayer || layer > endLayer)
0184     {
0185       continue;
0186     }
0187 
0188     const auto iter = positions.find(key);
0189 
0190     /// The wrong key was supplied...
0191     if (iter == positions.end())
0192     {
0193       continue;
0194     }
0195 
0196     // store (r,z)
0197     const Acts::Vector3& pos = iter->second;
0198     positions_2d.emplace_back(std::sqrt(square(pos.x()) + square(pos.y())), pos.z());
0199   }
0200 
0201   // cannot fit if there is less than 2 positions
0202   if( positions_2d.size() < 2 ) { return; }
0203 
0204   // do the fit
0205   const auto [slope, intercept] = TrackFitUtils::line_fit(positions_2d);
0206 
0207   // assign
0208   seed->set_slope(slope);
0209   seed->set_Z0(intercept);
0210 }
0211 
0212 //____________________________________________________________________________________
0213 float TrackSeedHelper::get_x(TrackSeed const* seed)
0214 {
0215   return findRoot(seed).first;
0216 }
0217 
0218 //____________________________________________________________________________________
0219 float TrackSeedHelper::get_y(TrackSeed const* seed)
0220 {
0221   return findRoot(seed).second;
0222 }
0223 
0224 //____________________________________________________________________________________
0225 float TrackSeedHelper::get_z(TrackSeed const* seed)
0226 {
0227   return seed->get_Z0();
0228 }
0229 
0230 //____________________________________________________________________________________
0231 Acts::Vector3 TrackSeedHelper::get_xyz(TrackSeed const* seed)
0232 {
0233   const auto [x,y] = findRoot(seed);
0234   return {x,y,seed->get_Z0()};
0235 }