13 #include "art/Framework/Services/Registry/ServiceHandle.h"
14 #include "fhiclcpp/ParameterSet.h"
21 #include "TDecompSVD.h"
34 namespace lar_cluster3d {
39 , m_minAllowedCosAng(0.7)
40 , m_pcaAlg(pset.
get<fhicl::ParameterSet>(
"PrincipalComponentsAlg"))
45 m_geometry = art::ServiceHandle<geo::Geometry const>{}.get();
53 bool foundGoodSeed(
false);
65 if (eigenVal0 > 5. && eigenVal1 > 0.001) {
79 hit3DList.resize(hitPairListPtr.size());
81 std::copy(hitPairListPtr.begin(), hitPairListPtr.end(), hit3DList.begin());
91 checkList.resize(hitPairListPtr.size());
93 std::copy(hitPairListPtr.begin(), hitPairListPtr.end(), checkList.begin());
95 std::reverse(checkList.begin(), checkList.end());
109 double seedDir[3] = {seedPca.getEigenVectors().row(2)(0),
110 seedPca.getEigenVectors().row(2)(1),
111 seedPca.getEigenVectors().row(2)(2)};
112 double seedStart[3] = {
113 hit3DList.front()->getX(), hit3DList.front()->getY(), hit3DList.front()->getZ()};
115 if (hit3DList.size() > 10) {
120 LineFit2DHits(hit3DList, seedStart[0], newSeedPos, newSeedDir, chiDOF);
124 double cosAng = seedDir[0] * newSeedDir[0] + seedDir[1] * newSeedDir[1] +
125 seedDir[2] * newSeedDir[2];
127 if (cosAng < 0.) newSeedDir *= -1.;
129 seedStart[0] = newSeedPos[0];
130 seedStart[1] = newSeedPos[1];
131 seedStart[2] = newSeedPos[2];
132 seedDir[0] = newSeedDir[0];
133 seedDir[1] = newSeedDir[1];
134 seedDir[2] = newSeedDir[2];
138 for (
const auto& hit3D : hit3DList)
139 hit3D->setStatusBit(0x40000000);
141 seedHitPairVec.emplace_back(std::pair<recob::Seed, reco::HitPairListPtr>(
144 foundGoodSeed =
true;
149 return foundGoodSeed;
156 bool foundGoodSeedHits(
false);
159 std::set<const reco::ClusterHit2D*> hit2DSet;
162 double lastArcLen = hit3DList.front()->getArclenToPoca();
164 reco::HitPairListPtr::iterator startItr = hit3DList.begin();
165 reco::HitPairListPtr::iterator lastItr = hit3DList.begin();
167 while (++lastItr != hit3DList.end()) {
176 for (
const auto& hit2D : hit3D->
getHits()) {
177 hit2DSet.insert(hit2D);
186 if (startItr != hit3DList.begin()) hit3DList.erase(hit3DList.begin(), startItr);
187 if (lastItr != hit3DList.end()) hit3DList.erase(lastItr, hit3DList.end());
201 double cosAng = primarySeedAxis.dot(planeVec0);
209 return foundGoodSeedHits;
218 double& ChiDOF)
const
241 std::set<const reco::ClusterHit2D*> hit2DSet;
243 for (
const auto& hit3D : hit3DList) {
244 for (
const auto& hit2D : hit3D->getHits())
245 hit2DSet.insert(hit2D);
248 if (hit2DSet.size() < 4)
return;
250 const unsigned int nvars = 4;
251 unsigned int npts = 3 * hit3DList.size();
253 TMatrixD
A(npts, nvars);
256 unsigned short ninpl[3] = {0};
257 unsigned short nok = 0;
258 unsigned short iht(0), cstat, tpc, ipl;
259 double x, cw, sw, off;
262 for (
const auto&
hit : hit2DSet) {
278 x =
hit->getXPosition() - XOrigin;
284 w[iht] = wireID.
Wire - off;
289 if (ninpl[ipl] == 2) ++nok;
299 TVectorD tVec = svd.Solve(w, ok);
304 if (npts <= 4)
return;
306 double ypr, zpr, diff;
308 for (
const auto&
hit : hit2DSet) {
317 x =
hit->getXPosition() - XOrigin;
318 ypr = tVec[0] + tVec[2] *
x;
319 zpr = tVec[1] + tVec[3] *
x;
320 diff = ypr * cw + zpr * sw - (wireID.
Wire - off);
321 ChiDOF += diff * diff;
326 ChiDOF /= (float)(npts - 4);
328 double norm = sqrt(1 + tVec[2] * tVec[2] + tVec[3] * tVec[3]);
330 Dir[1] = tVec[2] /
norm;
331 Dir[2] = tVec[3] /
norm;
geo::Length_t WireCoordinate(double YPos, double ZPos, geo::PlaneID const &planeid) const
Returns the index of the nearest wire to the specified position.
Define a comparator which will sort hits by arc length along a PCA axis.
void PCAAnalysis_calc3DDocas(const reco::HitPairListPtr &hitPairVector, const reco::PrincipalComponents &pca) const
bool getHitsAtEnd(reco::HitPairListPtr &hit3DList, reco::PrincipalComponents &seedPca) const
Separate function to find hits at the ends of the input hits.
geo::Geometry const * m_geometry
void PCAAnalysis_3D(const reco::HitPairListPtr &hitPairList, reco::PrincipalComponents &pca, bool skeletonOnly=false) const
process_name opflash particleana ie x
void flipAxis(size_t axis)
CryostatID_t Cryostat
Index of cryostat.
WireID_t Wire
Index of the wire within its plane.
PrincipalComponentsAlg m_pcaAlg
geo::Length_t WirePitch(geo::PlaneID const &planeid) const
Returns the distance between two consecutive wires.
bool findTrackSeeds(reco::HitPairListPtr &hitPairListPtr, reco::PrincipalComponents &inputPCA, SeedHitPairListPairVec &seedHitMap) const override
Given the list of hits this will search for candidate Seed objects and return them.
This is an algorithm for finding recob::Seed objects in 3D clusters.
Define a comparator which will sort hits by the absolute value of arc length so hits are ordered clos...
const EigenValues & getEigenValues() const
std::list< const reco::ClusterHit3D * > HitPairListPtr
PlaneID_t Plane
Index of the plane within its TPC.
auto norm(Vector const &v)
Return norm of the specified vector.
double m_minAllowedCosAng
The minimum cos(ang) between input and seed axes.
PCASeedFinderAlg(fhicl::ParameterSet const &pset)
Constructor.
std::vector< SeedHitPairListPair > SeedHitPairListPairVec
float getArclenToPoca() const
TPCID_t TPC
Index of the TPC within its cryostat.
void LineFit2DHits(const reco::HitPairListPtr &hitList, double XOrigin, TVector3 &Pos, TVector3 &Dir, double &ChiDOF) const
const ClusterHit2DVec & getHits() const
art framework interface to geometry description
const EigenVectors & getEigenVectors() const