36 mf::LogInfo(
"pma::PMAlgStitching") <<
"Passed " << tracks.
size() <<
" tracks for CPA stitching.";
45 mf::LogInfo(
"pma::PMAlgStitching") <<
"Passed " << tracks.
size() <<
" tracks for APA stitching.";
60 if (minTrkLength < 6) minTrkLength = 6;
64 while (t < tracks.
size()) {
67 if (t1->
Nodes().size() < minTrkLength) {
79 TVector3 trk1BackDir =
86 bool isBestFront1 =
false;
87 bool isBestFront2 =
false;
88 double xBestShift = 0;
89 double frontShift1 = t1->
Nodes()[0]->Point3D().X() - offsetFront1;
90 double backShift1 = t1->
Nodes()[t1->
Nodes().size() - 1]->Point3D().X() - offsetBack1;
92 double bestMatchScore = 99999;
94 for (
unsigned int u = t + 1; u < tracks.
size(); ++u) {
97 if (t2->
Nodes().size() < minTrkLength)
continue;
103 TVector3 trk2BackDir =
118 if (tpc1 == tpc2) giveUp =
true;
121 if (tpc1 == tpc2) giveUp =
true;
125 if (tpc1 == tpc2) giveUp =
true;
128 if (tpc1 == tpc2) giveUp =
true;
131 if (giveUp)
continue;
134 double surfaceGap = 10.0;
135 bool carryOn[4] = {
true,
true,
true,
true};
136 if (fabs(offsetFront1 - offsetFront2) > surfaceGap) carryOn[0] =
false;
137 if (fabs(offsetFront1 - offsetBack2) > surfaceGap) carryOn[1] =
false;
138 if (fabs(offsetBack1 - offsetFront2) > surfaceGap) carryOn[2] =
false;
139 if (fabs(offsetBack1 - offsetBack2) > surfaceGap) carryOn[3] =
false;
142 for (
int i = 0; i < 4; ++i) {
144 if (!carryOn[i])
continue;
153 t1Dir = trk1FrontDir;
154 xShift1 = frontShift1;
159 xShift1 = backShift1;
163 t2Dir = trk2FrontDir;
171 if (t1Dir.X() * t2Dir.X() > 0) {
continue; }
182 xBestShift = xShift1;
183 bestMatchScore = score;
184 if (i < 2) { isBestFront1 =
true; }
186 isBestFront1 =
false;
188 if (i % 2 == 0) { isBestFront2 =
true; }
190 isBestFront2 =
false;
193 <<
"Tracks " << t <<
" and " << u <<
" matching score = " << score << std::endl
194 <<
" - " << t1Pos.X() <<
", " << t1Pos.Y() <<
", " << t1Pos.Z() <<
" :: " << t1Dir.X()
195 <<
", " << t1Dir.Y() <<
", " << t1Dir.Z() << std::endl
196 <<
" - " << t2Pos.X() <<
", " << t2Pos.Y() <<
", " << t2Pos.Z() <<
" :: " << t2Dir.X()
197 <<
", " << t2Dir.Y() <<
", " << t2Dir.Z() << std::endl
199 <<
", " << t1->
BackTPC() << std::endl
201 <<
", " << t2->
BackTPC() << std::endl
202 <<
" - " << isBestFront1 <<
" :: " << isBestFront2 << std::endl;
208 if (bestTrkMatch != 0x0) {
212 bool reverse =
false;
215 if (isBestFront1 && isBestFront2) { flip1 =
true; }
217 else if (isBestFront1 && !isBestFront2) {
221 else if (!isBestFront1 && !isBestFront2) {
229 bool canMerge =
true;
230 if ((tid1 < 0) || (tid2 < 0)) {
232 <<
"Track not found in the collection." << std::endl;
236 std::vector<pma::Track3D*> newTracks;
237 if (t1->
Flip(detProp, newTracks)) {
238 mf::LogInfo(
"pma::PMAlgStitching") <<
"Track 1 flipped.";
241 mf::LogInfo(
"pma::PMAlgStitching") <<
"Unable to flip Track 1.";
244 for (
const auto ts : newTracks) {
246 tracks.
tracks().emplace_back(ts, -1, tid1);
251 std::vector<pma::Track3D*> newTracks;
252 if (bestTrkMatch->
Flip(detProp, newTracks)) {
253 mf::LogInfo(
"pma::PMAlgStitching") <<
"Track 2 flipped.";
256 mf::LogInfo(
"pma::PMAlgStitching") <<
"Unable to flip Track 1.";
259 for (
const auto ts : newTracks) {
261 tracks.
tracks().emplace_back(ts, -1, tid2);
269 mf::LogInfo(
"pma::PMAlgStitching") <<
"Merging tracks...";
277 tracks.
merge((
size_t)idx2, (
size_t)idx1);
287 tracks.
merge((
size_t)idx1, (
size_t)idx2);
314 double stepSize = 0.1;
315 double minShift = shift - (50. * stepSize);
316 double maxShift = shift + (50. * stepSize);
317 double bestShift = 99999;
318 double bestScore = 99999;
320 for (shift = minShift; shift <= maxShift; shift += stepSize) {
321 TVector3 newPos1 = pos1;
322 TVector3 newPos2 = pos2;
323 newPos1.SetX(pos1.X() - shift);
324 newPos2.SetX(pos2.X() + shift);
326 if (thisScore < bestScore) {
328 bestScore = thisScore;
340 TVector3& dir2)
const 343 double delta = -999.;
346 double steps1 = (pos2.X() - pos1.X()) / dir1.X();
347 double steps2 = (pos1.X() - pos2.X()) / dir2.X();
350 TVector3 trk1Merge = pos1 + steps1 * dir1;
351 TVector3 trk2Merge = pos2 + steps2 * dir2;
354 delta = (trk1Merge - pos2).Mag() + (trk2Merge - pos1).Mag();
364 auto const* geom = lar::providerFrom<geo::Geometry>();
372 unsigned int plane = 0;
373 bool hasPlane =
false;
374 for (; plane < 4; ++plane) {
376 if (hasPlane) {
break; }
379 if (!hasPlane) {
continue; }
389 double xmin = center.X() - tpcDim[0];
390 double xmax = center.X() + tpcDim[0];
391 double xCathode = 0.;
393 if (fabs(xmin - xAnode) > fabs(xmax - xAnode)) { xCathode = xmin; }
bool HasPlane(unsigned int iplane) const
Returns whether a plane with index iplane is present in this TPC.
Utilities related to art service access.
double GetTPCOffset(unsigned int tpc, unsigned int cryo, bool isCPA)
int getCandidateTreeId(pma::Track3D const *candidate) const
Implementation of the Projection Matching Algorithm.
Point_t const & GetCenter() const
Returns the centre of the wire plane in world coordinates [cm].
void StitchTracks(const detinfo::DetectorClocksData &clockData, const detinfo::DetectorPropertiesData &detProp, pma::TrkCandidateColl &tracks, bool isCPA)
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
void ApplyDriftShiftInTree(const detinfo::DetectorClocksData &clockData, detinfo::DetectorPropertiesData const &detProp, double dx, bool skipFirst=false)
Geometry information for a single TPC.
::fhicl::TupleAs< Point(::geo::Length_t,::geo::Length_t,::geo::Length_t)> Point3D
Atom object for reading a 3D point or vector (centimeters).
PMAlgStitching(const pma::PMAlgStitching::Config &config)
Implementation of the Projection Matching Algorithm.
double GetTrackPairDelta(TVector3 &pos1, TVector3 &pos2, TVector3 &dir1, TVector3 &dir2) const
unsigned int BackTPC() const
std::map< geo::TPCID, double > fTPCXOffsetsAPA
double Length() const
Length is associated with z coordinate [cm].
unsigned int fNodesFromEnd
unsigned int BackCryo() const
Access the description of detector geometry.
Point_t GetCenter() const
Returns the center of the TPC volume in world coordinates [cm].
double GetOptimalStitchShift(TVector3 &pos1, TVector3 &pos2, TVector3 &dir1, TVector3 &dir2, double &shift) const
bool setTreeOriginAtFront(detinfo::DetectorPropertiesData const &detProp, pma::Track3D *trk)
std::map< geo::TPCID, double > fTPCXOffsetsCPA
fhicl::Atom< int > StitchingThreshold
int getCandidateIndex(pma::Track3D const *candidate) const
unsigned int FrontTPC() const
unsigned int FrontCryo() const
The data type to uniquely identify a TPC.
void merge(size_t idx1, size_t idx2)
Track finding helper for the Projection Matching Algorithm.
double HalfHeight() const
Height is associated with y coordinate [cm].
Contains all timing reference information for the detector.
fhicl::Atom< unsigned int > NodesFromEnd
double fStitchingThreshold
void StitchTracksAPA(const detinfo::DetectorClocksData &clockData, const detinfo::DetectorPropertiesData &detProp, pma::TrkCandidateColl &tracks)
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
std::vector< pma::Node3D * > const & Nodes() const noexcept
IDparameter< geo::TPCID > TPCID
Member type of validated geo::TPCID parameter.
PlaneGeo const & Plane(geo::View_t view) const
Return the plane in the tpc with View_t view.
bool Flip(const detinfo::DetectorPropertiesData &detProp, std::vector< pma::Track3D * > &allTracks)
void StitchTracksCPA(const detinfo::DetectorClocksData &clockData, const detinfo::DetectorPropertiesData &detProp, pma::TrkCandidateColl &tracks)
art framework interface to geometry description
double HalfWidth() const
Width is associated with x coordinate [cm].
std::vector< TrkCandidate > const & tracks() const
cet::coded_exception< error, detail::translate > exception
Encapsulate the construction of a single detector plane.