30 #include "Eigen/Dense" 31 #include "Eigen/Eigenvalues" 32 #include "Eigen/Geometry" 33 #include "Eigen/Jacobi" 46 struct Sort3DHitsByDocaToAxis {
74 float doca3DScl)
const 106 int maxIterations(3);
110 maxRange = sclFctr * 0.5 * (maxRange + aveDoca);
113 int totalRejects(numRejHits);
114 int maxRejects(0.4 * hitPairVector.size());
117 while (maxIterations-- && numRejHits > 0 && totalRejects < maxRejects) {
143 bool skeletonOnly)
const 154 Eigen::Vector3d meanPos(Eigen::Vector3d::Zero());
155 double meanWeightSum(0.);
159 double minimumDeltaPeakSig(0.00001);
165 std::vector<double> hitChiSquareVec;
167 hitChiSquareVec.resize(hitPairVector.size());
169 std::transform(hitPairVector.begin(),
171 hitChiSquareVec.begin(),
172 [](
const auto&
hit) {
return hit->getHitChiSquare(); });
173 std::sort(hitChiSquareVec.begin(), hitChiSquareVec.end());
175 size_t numToKeep = 0.8 * hitChiSquareVec.size();
177 hitChiSquareVec.resize(numToKeep);
179 double aveValue = std::accumulate(hitChiSquareVec.begin(), hitChiSquareVec.end(), double(0.)) /
180 double(hitChiSquareVec.size());
181 double rms = std::sqrt(std::inner_product(hitChiSquareVec.begin(),
182 hitChiSquareVec.end(),
183 hitChiSquareVec.begin(),
186 [aveValue](
const auto&
left,
const auto&
right) {
187 return (
left - aveValue) * (
right - aveValue);
189 double(hitChiSquareVec.size()));
191 minimumDeltaPeakSig =
std::max(minimumDeltaPeakSig, aveValue - rms);
195 for (
const auto&
hit : hitPairVector) {
202 double(
hit->getHitChiSquare()));
205 meanPos(0) +=
hit->getPosition()[0] *
weight;
206 meanPos(1) +=
hit->getPosition()[1] *
weight;
207 meanPos(2) +=
hit->getPosition()[2] *
weight;
213 meanPos /= meanWeightSum;
222 double weightSum(0.);
225 for (
const auto&
hit : hitPairVector) {
231 double(
hit->getHitChiSquare()));
233 double x = (
hit->getPosition()[0] - meanPos(0)) * weight;
234 double y = (
hit->getPosition()[1] - meanPos(1)) * weight;
235 double z = (
hit->getPosition()[2] - meanPos(2)) * weight;
237 weightSum += weight *
weight;
250 sig << xi2, xiyi, xizi, xiyi, yi2, yizi, xizi, yizi, zi2;
252 sig *= 1. / weightSum;
254 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> eigenMat(sig);
256 if (eigenMat.info() == Eigen::ComputationInfo::Success) {
262 eigenMat.eigenvectors().transpose().cast<
float>();
265 if (std::isnan(recobEigenVals[0])) {
266 std::cout <<
"==> Third eigenvalue returns a nan" <<
std::endl;
268 recobEigenVals[0] = 0.;
271 recobEigenVecs.row(0) = recobEigenVecs.row(1).cross(recobEigenVecs.row(2));
276 true, numPairsInt, recobEigenVals, recobEigenVecs, meanPos.cast<
float>());
290 bool updateAvePos)
const 304 float aveHitDoca(0.);
305 Eigen::Vector3f avePosUpdate(0., 0., 0.);
316 std::vector<Eigen::Vector3f> hitPosVec;
319 for (
const auto& hit3D : hitPairVector) {
321 for (
const auto&
hit : hit3D->getHits()) {
329 double wirePosArr[3] = {0., 0., 0.};
332 Eigen::Vector3f wireCenter(wirePosArr[0], wirePosArr[1], wirePosArr[2]);
333 Eigen::Vector3f wireDirVec(
337 float hitPeak(
hit->getHit()->PeakTime());
339 Eigen::Vector3f wirePos(
345 Eigen::Vector3f xAxis(1., 0., 0.);
346 Eigen::Vector3f planeNormal =
347 xAxis.cross(wireDirVec);
349 float docaInPlane(wirePos[0] - avePosition[0]);
350 float arcLenToPlane(0.);
351 float cosAxisToPlaneNormal = axisDirVec.dot(planeNormal);
353 Eigen::Vector3f axisPlaneIntersection = wirePos;
354 Eigen::Vector3f hitPosTVec = wirePos;
356 if (fabs(cosAxisToPlaneNormal) > 0.) {
357 Eigen::Vector3f deltaPos = wirePos - avePosition;
359 arcLenToPlane = deltaPos.dot(planeNormal) / cosAxisToPlaneNormal;
360 axisPlaneIntersection = avePosition + arcLenToPlane * axisDirVec;
361 docaInPlane = wirePos[0] - axisPlaneIntersection[0];
363 Eigen::Vector3f axisToInter = axisPlaneIntersection - wirePos;
364 float arcLenToDoca = axisToInter.dot(wireDirVec);
366 hitPosTVec += arcLenToDoca * wireDirVec;
370 Eigen::Vector3f wVec = avePosition - wirePos;
373 float a(axisDirVec.dot(axisDirVec));
374 float b(axisDirVec.dot(wireDirVec));
375 float c(wireDirVec.dot(wireDirVec));
376 float d(axisDirVec.dot(wVec));
377 float e(wireDirVec.dot(wVec));
379 float den(
a *
c -
b *
b);
385 arcLen1 = (b *
e -
c *
d) / den;
386 arcLen2 = (
a *
e - b *
d) / den;
400 Eigen::Vector3f hitPos = wirePos + arcLen2 * wireDirVec;
401 Eigen::Vector3f axisPos = avePosition + arcLen1 * axisDirVec;
402 float deltaX = hitPos(0) - axisPos(0);
403 float deltaY = hitPos(1) - axisPos(1);
404 float deltaZ = hitPos(2) - axisPos(2);
405 float doca2 = deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ;
406 float doca = sqrt(doca2);
410 aveHitDoca += fabs(docaInPlane);
425 hit->setDocaToAxis(fabs(docaInPlane));
426 hit->setArcLenToPoca(arcLenToPlane);
430 if (
hit->getStatusBits() & 0x80) {
continue; }
434 avePosUpdate += hitPosTVec;
436 hitPosVec.push_back(hitPosTVec);
443 avePosUpdate /=
float(nHits);
446 aveHitDoca /=
float(nHits);
448 if (updateAvePos) { avePosition = avePosUpdate; }
451 for (
auto& hitPos : hitPosVec) {
453 float x = hitPos[0] - avePosition[0];
454 float y = hitPos[1] - avePosition[1];
455 float z = hitPos[2] - avePosition[2];
470 sig << xi2, xiyi, xizi, xiyi, yi2, yizi, xizi, yizi, zi2;
472 sig *= 1. / (nHits - 1);
474 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3f> eigenMat(sig);
476 if (eigenMat.info() == Eigen::ComputationInfo::Success) {
482 eigenMat.eigenvectors().transpose().cast<
float>();
486 true, nHits, recobEigenVals, recobEigenVecs, avePosition, aveHitDoca);
505 Eigen::Vector3f avePosition(
513 for (
const auto* clusterHit3D : hitPairVector) {
515 clusterHit3D->clearStatusBits(0x80);
519 Eigen::Vector3f clusPos(clusterHit3D->getPosition()[0],
520 clusterHit3D->getPosition()[1],
521 clusterHit3D->getPosition()[2]);
524 Eigen::Vector3f clusToHitVec = clusPos - avePosition;
527 float arclenToPoca = clusToHitVec.dot(axisDirVec);
530 Eigen::Vector3f docaPos = avePosition + arclenToPoca * axisDirVec;
533 Eigen::Vector3f docaPosToClusPos = clusPos - docaPos;
534 float docaToAxis = docaPosToClusPos.norm();
536 aveDoca3D += docaToAxis;
539 clusterHit3D->setDocaToAxis(docaToAxis);
540 clusterHit3D->setArclenToPoca(arclenToPoca);
544 aveDoca3D /=
float(hitPairVector.size());
560 Eigen::Vector3f avePosition(
568 float aveHitDoca(0.);
571 for (
const auto*
hit : hit2DListPtr) {
580 double wirePosArr[3] = {0., 0., 0.};
583 Eigen::Vector3f wireCenter(wirePosArr[0], wirePosArr[1], wirePosArr[2]);
584 Eigen::Vector3f wireDirVec(
588 Eigen::Vector3f wirePos(
hit->getXPosition(), wireCenter[1], wireCenter[2]);
591 Eigen::Vector3f xAxis(1., 0., 0.);
592 Eigen::Vector3f planeNormal =
593 xAxis.cross(wireDirVec);
595 float arcLenToPlane(0.);
596 float docaInPlane(wirePos[0] - avePosition[0]);
597 float cosAxisToPlaneNormal = axisDirVec.dot(planeNormal);
599 Eigen::Vector3f axisPlaneIntersection = wirePos;
602 if (fabs(cosAxisToPlaneNormal) > 0.) {
603 Eigen::Vector3f deltaPos = wirePos - avePosition;
606 std::min(
float(deltaPos.dot(planeNormal) / cosAxisToPlaneNormal), maxArcLen);
607 axisPlaneIntersection = avePosition + arcLenToPlane * axisDirVec;
609 Eigen::Vector3f axisToInter = axisPlaneIntersection - wirePos;
610 float arcLenToDoca = axisToInter.dot(wireDirVec);
613 if (fabs(arcLenToDoca) > wire_geom.
HalfL()) arcLenToDoca = wire_geom.
HalfL();
618 Eigen::Vector3f docaVec = axisPlaneIntersection - (wirePos + arcLenToDoca * wireDirVec);
619 docaInPlane = docaVec.norm();
622 aveHitDoca += fabs(docaInPlane);
625 hit->setDocaToAxis(fabs(docaInPlane));
626 hit->setArcLenToPoca(arcLenToPlane);
630 aveHitDoca /=
float(hit2DListPtr.size());
640 float maxDocaAllowed)
const 650 for (
const auto& hit3D : hitPairVector) {
652 for (
const auto&
hit : hit3D->getHits()) {
654 hit->clearStatusBits(0x80);
656 if (
hit->getDocaToAxis() > maxDocaAllowed) {
657 hit->setStatusBit(0x80);
669 float maxDocaAllowed)
const 679 Eigen::Vector3f avePosition(
684 for (
const auto* clusterHit3D : hitPairVector) {
686 clusterHit3D->clearStatusBits(0x80);
690 Eigen::Vector3f clusPos(clusterHit3D->getPosition()[0],
691 clusterHit3D->getPosition()[1],
692 clusterHit3D->getPosition()[2]);
695 Eigen::Vector3f clusToHitVec = clusPos - avePosition;
698 float arclenToPoca = clusToHitVec.dot(axisDirVec);
701 Eigen::Vector3f docaPos = avePosition + arclenToPoca * axisDirVec;
704 Eigen::Vector3f docaPosToClusPos = clusPos - docaPos;
705 float docaToAxis = docaPosToClusPos.norm();
708 clusterHit3D->setDocaToAxis(docaToAxis);
709 clusterHit3D->setArclenToPoca(arclenToPoca);
712 if (clusterHit3D->getDocaToAxis() > maxDocaAllowed) {
713 clusterHit3D->setStatusBit(0x80);
Geometry description of a TPC wireThe wire is a single straight segment on a wire plane...
void setAveHitDoca(double doca) const
void PCAAnalysis_2D(const reco::HitPairListPtr &hitPairVector, reco::PrincipalComponents &pca, bool updateAvePos=false) const
std::list< const reco::ClusterHit2D * > Hit2DListPtr
export some data structure definitions
void PCAAnalysis_calc3DDocas(const reco::HitPairListPtr &hitPairVector, const reco::PrincipalComponents &pca) const
void PCAAnalysis_3D(const reco::HitPairListPtr &hitPairList, reco::PrincipalComponents &pca, bool skeletonOnly=false) const
PrincipalComponentsAlg(fhicl::ParameterSet const &pset)
Constructor.
double rms(sqlite3 *db, std::string const &table_name, std::string const &column_name)
geo::Geometry * m_geometry
CryostatID_t Cryostat
Index of cryostat.
int PCAAnalysis_reject2DOutliers(const reco::HitPairListPtr &hitPairVector, reco::PrincipalComponents &pca, double aveHitDoca) const
bool operator()(const reco::ClusterHit3D *left, const reco::ClusterHit3D *right) const
float getDocaToAxis() const
art framework interface to geometry description
const EigenValues & getEigenValues() const
Eigen::Vector3f EigenValues
void PCAAnalysis(const reco::HitPairListPtr &hitPairVector, reco::PrincipalComponents &pca, double doca3DScl=3.) const
Run the Principal Components Analysis.
T get(std::string const &key) const
const Eigen::Vector3f & getAvePosition() const
double m_parallel
means lines are parallel
bool operator()(const reco::ClusterHit3D *left, const reco::ClusterHit3D *right) const
int PCAAnalysis_reject3DOutliers(const reco::HitPairListPtr &hitPairVector, const reco::PrincipalComponents &pca, double aveHitDoca) const
std::list< const reco::ClusterHit3D * > HitPairListPtr
static int max(int a, int b)
PlaneID_t Plane
Index of the plane within its TPC.
Definition of data types for geometry description.
Detector simulation of raw signals on wires.
Encapsulate the geometry of a wire.
double ConvertTicksToX(double ticks, int p, int t, int c) const
double HalfL() const
Returns half the length of the wire [cm].
Declaration of signal hit object.
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
const float getAveHitDoca() const
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
bool operator()(const reco::ClusterHit3D *left, const reco::ClusterHit3D *right) const
Eigen::Matrix3f EigenVectors
float getArclenToPoca() const
void GetCenter(double *xyz, double localz=0.0) const
Fills the world coordinate of a point on the wire.
TPCID_t TPC
Index of the TPC within its cryostat.
void PCAAnalysis_calc2DDocas(const reco::Hit2DListPtr &hit2DVector, const reco::PrincipalComponents &pca) const
const EigenVectors & getEigenVectors() const
QTextStream & endl(QTextStream &s)
WireGeo const & WireIDToWireGeo(geo::WireID const &wireid) const