19 #include "lardata/RecoObjects/Cluster3D.h" 28 #include "TDecompSVD.h" 61 const TVector3& axisDir,
75 double wirePos[3] = {0.,0.,0.};
86 TVector3 wVec(axisPos.X()-wirePos[0], axisPos.Y()-wirePos[1], axisPos.Z()-wirePos[2]);
89 double a(axisDir.Dot(axisDir));
90 double b(axisDir.Dot(wireDir));
91 double c(wireDir.Dot(wireDir));
92 double d(axisDir.Dot(wVec));
93 double e(wireDir.Dot(wVec));
95 double den(
a*
c -
b*
b);
100 arcLenAxis = (b*
e -
c*
d) / den;
101 arcLenWire = (
a*
e - b*
d) / den;
111 poca = TVector3(wirePos[0] + arcLenWire * wireDir[0],
112 wirePos[1] + arcLenWire * wireDir[1],
113 wirePos[2] + arcLenWire * wireDir[2]);
114 TVector3 axisPocaPos(axisPos[0] + arcLenAxis * axisDir[0],
115 axisPos[1] + arcLenAxis * axisDir[1],
116 axisPos[2] + arcLenAxis * axisDir[2]);
118 double deltaX(poca.X() - axisPocaPos.X());
119 double deltaY(poca.Y() - axisPocaPos.Y());
120 double deltaZ(poca.Z() - axisPocaPos.Z());
121 double doca2(deltaX*deltaX + deltaY*deltaY + deltaZ*deltaZ);
191 int maxIterations(3);
195 maxRange = sclFctr * 0.5*(maxRange+aveDoca);
198 int totalRejects(numRejHits);
199 int maxRejects(0.4*hitPairVector.size());
202 while(maxIterations-- && numRejHits > 0 && totalRejects < maxRejects)
236 double meanPos[] = {0.,0.,0.};
239 for (
const auto&
hit : hitPairVector)
241 if (skeletonOnly && !((
hit->getStatusBits() & 0x10000000) == 0x10000000))
continue;
243 meanPos[0] +=
hit->getPosition()[0];
244 meanPos[1] +=
hit->getPosition()[1];
245 meanPos[2] +=
hit->getPosition()[2];
249 double numPairs = double(numPairsInt);
251 meanPos[0] /= numPairs;
252 meanPos[1] /= numPairs;
253 meanPos[2] /= numPairs;
264 for (
const auto&
hit : hitPairVector)
266 if (skeletonOnly && !((
hit->getStatusBits() & 0x10000000) == 0x10000000))
continue;
268 double x =
hit->getPosition()[0] - meanPos[0];
269 double y =
hit->getPosition()[1] - meanPos[1];
270 double z =
hit->getPosition()[2] - meanPos[2];
281 TMatrixD sigma(3, 3);
284 sigma(0,1) = sigma(1,0) = xiyi;
285 sigma(0,2) = sigma(2,0) = xizi;
287 sigma(1,2) = sigma(2,1) = yizi;
291 sigma *= (1./(numPairs - 1.));
294 TDecompSVD rootSVD(sigma);
301 svdOk = rootSVD.Decompose();
312 TVectorD eigenVals = rootSVD.GetSig();
313 TMatrixD eigenVecs = rootSVD.GetU();
316 double recobEigenVals[] = {eigenVals[0], eigenVals[1], eigenVals[2]};
320 std::vector<double> tempVec;
323 tempVec.push_back(eigenVecs(0, 0));
324 tempVec.push_back(eigenVecs(1, 0));
325 tempVec.push_back(eigenVecs(2, 0));
326 recobEigenVecs.push_back(tempVec);
330 tempVec.push_back(eigenVecs(0, 1));
331 tempVec.push_back(eigenVecs(1, 1));
332 tempVec.push_back(eigenVecs(2, 1));
333 recobEigenVecs.push_back(tempVec);
337 tempVec.push_back(eigenVecs(0, 2));
338 tempVec.push_back(eigenVecs(1, 2));
339 tempVec.push_back(eigenVecs(2, 2));
340 recobEigenVecs.push_back(tempVec);
367 double aveHitDoca(0.);
368 TVector3 avePosUpdate(0.,0.,0.);
379 std::vector<TVector3> hitPosVec;
382 for (
const auto& hit3D : hitPairVector)
385 for (
const auto&
hit : hit3D->getHits())
394 double wirePosArr[3] = {0.,0.,0.};
397 TVector3 wireCenter(wirePosArr[0], wirePosArr[1], wirePosArr[2]);
398 TVector3 wireDirVec(wire_geom.
Direction());
401 double hitPeak(
hit->getHit().PeakTime());
406 TVector3 xAxis(1.,0.,0.);
407 TVector3 planeNormal = xAxis.Cross(wireDirVec);
409 double docaInPlane(wirePos[0] - avePosition[0]);
410 double arcLenToPlane(0.);
411 double cosAxisToPlaneNormal = axisDirVec.Dot(planeNormal);
413 TVector3 axisPlaneIntersection = wirePos;
414 TVector3 hitPosTVec = wirePos;
416 if (fabs(cosAxisToPlaneNormal) > 0.)
418 TVector3 deltaPos = wirePos - avePosition;
420 arcLenToPlane = deltaPos.Dot(planeNormal) / cosAxisToPlaneNormal;
421 axisPlaneIntersection = avePosition + arcLenToPlane * axisDirVec;
422 docaInPlane = wirePos[0] - axisPlaneIntersection[0];
424 TVector3 axisToInter = axisPlaneIntersection - wirePos;
425 double arcLenToDoca = axisToInter.Dot(wireDirVec);
427 hitPosTVec += arcLenToDoca * wireDirVec;
431 TVector3 wVec = avePosition - wirePos;
434 double a(axisDirVec.Dot(axisDirVec));
435 double b(axisDirVec.Dot(wireDirVec));
436 double c(wireDirVec.Dot(wireDirVec));
437 double d(axisDirVec.Dot(wVec));
438 double e(wireDirVec.Dot(wVec));
440 double den(
a*
c -
b*
b);
447 arcLen1 = (b*
e -
c*
d) / den;
448 arcLen2 = (
a*
e - b*
d) / den;
463 TVector3 hitPos = wirePos + arcLen2 * wireDirVec;
464 TVector3 axisPos = avePosition + arcLen1 * axisDirVec;
465 double deltaX = hitPos[0] - axisPos[0];
466 double deltaY = hitPos[1] - axisPos[1];
467 double deltaZ = hitPos[2] - axisPos[2];
468 double doca2 = deltaX*deltaX + deltaY*deltaY + deltaZ*deltaZ;
469 double doca = sqrt(doca2);
473 aveHitDoca += fabs(docaInPlane);
488 hit->setDocaToAxis(fabs(docaInPlane));
489 hit->setArcLenToPoca(arcLenToPlane);
493 if (
hit->getStatusBits() & 0x80)
500 avePosUpdate += hitPosTVec;
502 hitPosVec.push_back(hitPosTVec);
509 avePosUpdate[0] /= double(nHits);
510 avePosUpdate[1] /= double(nHits);
511 avePosUpdate[2] /= double(nHits);
514 aveHitDoca /= double(nHits);
518 avePosition = avePosUpdate;
522 for(
auto& hitPos : hitPosVec)
525 double x = hitPos[0] - avePosition[0];
526 double y = hitPos[1] - avePosition[1];
527 double z = hitPos[2] - avePosition[2];
540 TMatrixD sigma(3, 3);
543 sigma(0,1) = sigma(1,0) = xiyi;
544 sigma(0,2) = sigma(2,0) = xizi;
546 sigma(1,2) = sigma(2,1) = yizi;
550 sigma *= (1./(nHits - 1.));
553 TDecompSVD rootSVD(sigma);
560 svdOk = rootSVD.Decompose();
571 TVectorD eigenVals = rootSVD.GetSig();
572 TMatrixD eigenVecs = rootSVD.GetU();
575 double recobEigenVals[] = {eigenVals[0], eigenVals[1], eigenVals[2]};
579 std::vector<double> tempVec;
582 tempVec.push_back(eigenVecs(0, 0));
583 tempVec.push_back(eigenVecs(1, 0));
584 tempVec.push_back(eigenVecs(2, 0));
585 recobEigenVecs.push_back(tempVec);
589 tempVec.push_back(eigenVecs(0, 1));
590 tempVec.push_back(eigenVecs(1, 1));
591 tempVec.push_back(eigenVecs(2, 1));
592 recobEigenVecs.push_back(tempVec);
596 tempVec.push_back(eigenVecs(0, 2));
597 tempVec.push_back(eigenVecs(1, 2));
598 tempVec.push_back(eigenVecs(2, 2));
599 recobEigenVecs.push_back(tempVec);
602 double avePosToSave[] = {avePosition[0],avePosition[1],avePosition[2]};
627 double aveDoca3D(0.);
630 for (
const auto* clusterHit3D : hitPairVector)
633 clusterHit3D->clearStatusBits(0x80);
637 TVector3 clusPos(clusterHit3D->getPosition()[0],clusterHit3D->getPosition()[1],clusterHit3D->getPosition()[2]);
640 TVector3 clusToHitVec = clusPos - avePosition;
643 double arclenToPoca = clusToHitVec.Dot(axisDirVec);
646 TVector3 docaPos = avePosition + arclenToPoca * axisDirVec;
649 TVector3 docaPosToClusPos = clusPos - docaPos;
650 double docaToAxis = docaPosToClusPos.Mag();
652 aveDoca3D += docaToAxis;
655 clusterHit3D->setDocaToAxis(docaToAxis);
656 clusterHit3D->setArclenToPoca(arclenToPoca);
660 aveDoca3D /= double(hitPairVector.size());
682 double aveHitDoca(0.);
685 for (
const auto*
hit : hit2DListPtr)
695 double wirePosArr[3] = {0.,0.,0.};
698 TVector3 wireCenter(wirePosArr[0], wirePosArr[1], wirePosArr[2]);
699 TVector3 wireDirVec(wire_geom.
Direction());
702 TVector3 wirePos(
hit->getXPosition(), wireCenter[1], wireCenter[2]);
705 TVector3 xAxis(1.,0.,0.);
706 TVector3 planeNormal = xAxis.Cross(wireDirVec);
708 double arcLenToPlane(0.);
709 double docaInPlane(wirePos[0] - avePosition[0]);
710 double cosAxisToPlaneNormal = axisDirVec.Dot(planeNormal);
712 TVector3 axisPlaneIntersection = wirePos;
715 if (fabs(cosAxisToPlaneNormal) > 0.)
717 TVector3 deltaPos = wirePos - avePosition;
719 arcLenToPlane =
std::min(deltaPos.Dot(planeNormal) / cosAxisToPlaneNormal, maxArcLen);
720 axisPlaneIntersection = avePosition + arcLenToPlane * axisDirVec;
721 TVector3 axisToInter = axisPlaneIntersection - wirePos;
722 double arcLenToDoca = axisToInter.Dot(wireDirVec);
725 if (fabs(arcLenToDoca) > wire_geom.
HalfL()) arcLenToDoca = wire_geom.
HalfL();
730 TVector3 docaVec = axisPlaneIntersection - (wirePos + arcLenToDoca * wireDirVec);
731 docaInPlane = docaVec.Mag();
734 aveHitDoca += fabs(docaInPlane);
737 hit->setDocaToAxis(fabs(docaInPlane));
738 hit->setArcLenToPoca(arcLenToPlane);
742 aveHitDoca /= double(hit2DListPtr.size());
751 double maxDocaAllowed)
const 761 for (
const auto& hit3D : hitPairVector)
764 for (
const auto&
hit : hit3D->getHits())
767 hit->clearStatusBits(0x80);
769 if (
hit->getDocaToAxis() > maxDocaAllowed)
771 hit->setStatusBit(0x80);
782 double maxDocaAllowed)
const 796 for (
const auto* clusterHit3D : hitPairVector)
799 clusterHit3D->clearStatusBits(0x80);
803 TVector3 clusPos(clusterHit3D->getPosition()[0],clusterHit3D->getPosition()[1],clusterHit3D->getPosition()[2]);
806 TVector3 clusToHitVec = clusPos - avePosition;
809 double arclenToPoca = clusToHitVec.Dot(axisDirVec);
812 TVector3 docaPos = avePosition + arclenToPoca * axisDirVec;
815 TVector3 docaPosToClusPos = clusPos - docaPos;
816 double docaToAxis = docaPosToClusPos.Mag();
819 clusterHit3D->setDocaToAxis(docaToAxis);
820 clusterHit3D->setArclenToPoca(arclenToPoca);
823 if (clusterHit3D->getDocaToAxis() > maxDocaAllowed)
825 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.
bool operator()(const reco::ClusterHit3D *left, const reco::ClusterHit3D *right)
geo::Geometry * m_geometry
geo::WireID WireID() const
void reconfigure(fhicl::ParameterSet const &pset)
a handler for the case where the algorithm control parameters are to be reset
Declaration of signal hit object.
CryostatID_t Cryostat
Index of cryostat.
int PCAAnalysis_reject2DOutliers(const reco::HitPairListPtr &hitPairVector, reco::PrincipalComponents &pca, double aveHitDoca) const
float getDocaToAxis() const
art framework interface to geometry description
const recob::Hit * getHit() const
const EigenValues & getEigenValues() const
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
int PCAAnalysis_reject3DOutliers(const reco::HitPairListPtr &hitPairVector, const reco::PrincipalComponents &pca, double aveHitDoca) const
std::list< const reco::ClusterHit3D * > HitPairListPtr
PlaneID_t Plane
Index of the plane within its TPC.
Detector simulation of raw signals on wires.
Encapsulate the geometry of a wire.
double HalfL() const
Returns half the length of the wire [cm].
float PeakTime() const
Time of the signal peak, in tick units.
void getHit2DPocaToAxis(const TVector3 &axisPos, const TVector3 &axisDir, const reco::ClusterHit2D *hit2D, TVector3 &poca, double &arcLenAxis, double &arcLenWire, double &doca)
This is used to get the poca, doca and arclen along cluster axis to 2D hit.
Utility object to perform functions of association.
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
bool operator()(const reco::ClusterHit3D *left, const reco::ClusterHit3D *right)
Encapsulate the construction of a single detector plane.
const float getAveHitDoca() const
virtual ~PrincipalComponentsAlg()
Destructor.
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
Eigen::Matrix3f EigenVectors
float getArclenToPoca() const
bool operator()(const reco::ClusterHit3D *left, const reco::ClusterHit3D *right)
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 detinfo::DetectorProperties * m_detector
const EigenVectors & getEigenVectors() const
QTextStream & endl(QTextStream &s)
WireGeo const & WireIDToWireGeo(geo::WireID const &wireid) const