13 #include <Eigen/Dense> 21 void LArPcaHelper::RunPca(
const T &t, CartesianVector ¢roid,
EigenValues &outputEigenValues,
EigenVectors &outputEigenVectors)
25 for (
const auto &point : t)
26 weightedPointVector.push_back(std::make_pair(LArObjectHelper::TypeAdaptor::GetPosition(point), 1.));
28 return LArPcaHelper::RunPca(weightedPointVector, centroid, outputEigenValues, outputEigenVectors);
42 if (pointVector.empty())
44 std::cout <<
"LArPcaHelper::RunPca - no three dimensional hits provided" << std::endl;
45 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
48 double meanPosition[3] = {0., 0., 0.};
53 const CartesianVector &point(weightedPoint.first);
54 const double weight(weightedPoint.second);
58 std::cout <<
"LArPcaHelper::RunPca - negative weight found" << std::endl;
59 throw StatusCodeException(STATUS_CODE_NOT_ALLOWED);
62 meanPosition[0] +=
static_cast<double>(point.GetX()) * weight;
63 meanPosition[1] +=
static_cast<double>(point.GetY()) * weight;
64 meanPosition[2] +=
static_cast<double>(point.GetZ()) * weight;
68 if (std::fabs(sumWeight) < std::numeric_limits<double>::epsilon())
70 std::cout <<
"LArPcaHelper::RunPca - sum of weights is zero" << std::endl;
71 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
74 meanPosition[0] /= sumWeight;
75 meanPosition[1] /= sumWeight;
76 meanPosition[2] /= sumWeight;
77 centroid = CartesianVector(meanPosition[0], meanPosition[1], meanPosition[2]);
89 const CartesianVector &point(weightedPoint.first);
90 const double weight(weightedPoint.second);
91 const double x(static_cast<double>((point.GetX()) - meanPosition[0]));
92 const double y(static_cast<double>((point.GetY()) - meanPosition[1]));
93 const double z(static_cast<double>((point.GetZ()) - meanPosition[2]));
106 sig << xi2, xiyi, xizi, xiyi, yi2, yizi, xizi, yizi, zi2;
108 sig *= 1. / sumWeight;
110 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3f> eigenMat(sig);
112 if (eigenMat.info() != Eigen::ComputationInfo::Success)
114 std::cout <<
"LArPcaHelper::RunPca - decomposition failure, nThreeDHits = " << pointVector.size() << std::endl;
115 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
118 typedef std::pair<float, size_t> EigenValColPair;
119 typedef std::vector<EigenValColPair> EigenValColVector;
121 EigenValColVector eigenValColVector;
122 const auto &resultEigenMat(eigenMat.eigenvalues());
123 eigenValColVector.emplace_back(resultEigenMat(0), 0);
124 eigenValColVector.emplace_back(resultEigenMat(1), 1);
125 eigenValColVector.emplace_back(resultEigenMat(2), 2);
127 std::sort(eigenValColVector.begin(), eigenValColVector.end(),
128 [](
const EigenValColPair &
left,
const EigenValColPair &
right) {
return left.first >
right.first; });
131 outputEigenValues = CartesianVector(eigenValColVector.at(0).first, eigenValColVector.at(1).first, eigenValColVector.at(2).first);
134 const Eigen::Matrix3f &eigenVecs(eigenMat.eigenvectors());
136 for (
const EigenValColPair &pair : eigenValColVector)
137 outputEigenVectors.emplace_back(eigenVecs(0, pair.second), eigenVecs(1, pair.second), eigenVecs(2, pair.second));
142 template void LArPcaHelper::RunPca(
const CartesianPointVector &, CartesianVector &,
EigenValues &,
EigenVectors &);
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
pandora::CartesianVector EigenValues
std::pair< const pandora::CartesianVector, double > WeightedPoint
std::vector< WeightedPoint > WeightedPointVector
Header file for the principal curve analysis helper class.
Header file for the object helper class.
Header file for the cluster helper class.
constexpr auto const & left(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
std::vector< pandora::CartesianVector > EigenVectors