38 mf::LogInfo(
"pma::PMAlgStitching") <<
"Passed " << tracks.
size() <<
" tracks for CPA stitching.";
44 mf::LogInfo(
"pma::PMAlgStitching") <<
"Passed " << tracks.
size() <<
" tracks for APA stitching.";
55 if(minTrkLength < 6) minTrkLength = 6;
59 while(t < tracks.
size()){
62 if(t1->
Nodes().size() < minTrkLength) { ++t;
continue; }
77 bool isBestFront1 =
false;
78 bool isBestFront2 =
false;
79 double xBestShift = 0;
80 double frontShift1 = t1->
Nodes()[0]->Point3D().X() - offsetFront1;
81 double backShift1 = t1->
Nodes()[t1->
Nodes().size()-1]->Point3D().X() - offsetBack1;
83 double bestMatchScore = 99999;
85 for(
unsigned int u = t+1; u < tracks.
size(); ++u){
88 if(t2->
Nodes().size() < minTrkLength)
continue;
108 if(tpc1 == tpc2) giveUp =
true;
111 if(tpc1 == tpc2) giveUp =
true;
115 if(tpc1 == tpc2) giveUp =
true;
118 if(tpc1 == tpc2) giveUp =
true;
124 double surfaceGap = 10.0;
125 bool carryOn[4] = {
true,
true,
true,
true};
126 if(fabs(offsetFront1 - offsetFront2) > surfaceGap) carryOn[0] =
false;
127 if(fabs(offsetFront1 - offsetBack2) > surfaceGap) carryOn[1] =
false;
128 if(fabs(offsetBack1 - offsetFront2) > surfaceGap) carryOn[2] =
false;
129 if(fabs(offsetBack1 - offsetBack2) > surfaceGap) carryOn[3] =
false;
132 for(
int i = 0; i < 4; ++i){
134 if(!carryOn[i])
continue;
143 t1Dir = trk1FrontDir;
144 xShift1 = frontShift1;
149 xShift1 = backShift1;
153 t2Dir = trk2FrontDir;
161 if(t1Dir.X() * t2Dir.X() > 0){
174 xBestShift = xShift1;
175 bestMatchScore = score;
180 isBestFront1 =
false;
186 isBestFront2 =
false;
188 mf::LogInfo(
"pma::PMAlgStitcher") <<
"Tracks " << t <<
" and " << u <<
" matching score = " << score << std::endl
189 <<
" - " << t1Pos.X() <<
", " << t1Pos.Y() <<
", " << t1Pos.Z() <<
" :: " << t1Dir.X() <<
", " << t1Dir.Y() <<
", " << t1Dir.Z() << std::endl
190 <<
" - " << t2Pos.X() <<
", " << t2Pos.Y() <<
", " << t2Pos.Z() <<
" :: " << t2Dir.X() <<
", " << t2Dir.Y() <<
", " << t2Dir.Z() << std::endl
193 <<
" - " << isBestFront1 <<
" :: " << isBestFront2 << std::endl;
199 if(bestTrkMatch != 0x0){
203 bool reverse =
false;
206 if(isBestFront1 && isBestFront2){
210 else if(isBestFront1 && !isBestFront2){
214 else if(!isBestFront1 && !isBestFront2){
222 bool canMerge =
true;
223 if ((tid1 < 0) || (tid2 < 0))
225 throw cet::exception(
"pma::PMAlgStitching") <<
"Track not found in the collection." << std::endl;
229 std::vector< pma::Track3D* > newTracks;
230 if(t1->
Flip(newTracks)){
231 mf::LogInfo(
"pma::PMAlgStitching") <<
"Track 1 flipped.";
234 mf::LogInfo(
"pma::PMAlgStitching") <<
"Unable to flip Track 1.";
237 for (
const auto ts : newTracks){
238 tracks.
tracks().emplace_back(ts, -1, tid1);
243 std::vector< pma::Track3D* > newTracks;
244 if(bestTrkMatch->
Flip(newTracks)){
245 mf::LogInfo(
"pma::PMAlgStitching") <<
"Track 2 flipped.";
248 mf::LogInfo(
"pma::PMAlgStitching") <<
"Unable to flip Track 1.";
251 for (
const auto ts : newTracks){
252 tracks.
tracks().emplace_back(ts, -1, tid2);
261 mf::LogInfo(
"pma::PMAlgStitching") <<
"Merging tracks...";
267 else {
mf::LogWarning(
"pma::PMAlgStitching") <<
" could not merge."; ++t; }
272 else {
mf::LogWarning(
"pma::PMAlgStitching") <<
" could not merge."; ++t; }
285 double stepSize = 0.1;
286 double minShift = shift - (50. * stepSize);
287 double maxShift = shift + (50. * stepSize);
288 double bestShift = 99999;
289 double bestScore = 99999;
291 for(shift = minShift; shift <= maxShift; shift += stepSize){
292 TVector3 newPos1 = pos1;
293 TVector3 newPos2 = pos2;
294 newPos1.SetX(pos1.X() - shift);
295 newPos2.SetX(pos2.X() + shift);
297 if(thisScore < bestScore){
299 bestScore = thisScore;
310 double delta = -999.;
313 double steps1 = (pos2.X() - pos1.X()) / dir1.X();
314 double steps2 = (pos1.X() - pos2.X()) / dir2.X();
317 TVector3 trk1Merge = pos1 + steps1*dir1;
318 TVector3 trk2Merge = pos2 + steps2*dir2;
321 delta = (trk1Merge-pos2).Mag() + (trk2Merge-pos1).Mag();
331 auto const* geom = lar::providerFrom<geo::Geometry>();
334 for (
geo::TPCID const& tID: geom->IterateTPCIDs()) {
339 unsigned int plane = 0;
340 bool hasPlane =
false;
341 for(;plane < 4; ++plane){
359 double center[3] = {0.};
362 double xmin = center[0] - tpcDim[0];
363 double xmax = center[0] + tpcDim[0];
364 double xCathode = 0.;
366 if(fabs(xmin - xAnode) > fabs(xmax-xAnode)){
double GetTrackPairDelta(TVector3 &pos1, TVector3 &pos2, TVector3 &dir1, TVector3 &dir2)
bool HasPlane(unsigned int iplane) const
Returns whether a plane with index iplane is present in this TPC.
double GetTPCOffset(unsigned int tpc, unsigned int cryo, bool isCPA)
int getCandidateTreeId(pma::Track3D const *candidate) const
unsigned int FrontTPC(void) const
unsigned int BackTPC(void) const
bool Flip(std::vector< pma::Track3D * > &allTracks)
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
::fhicl::TupleAs< Point(::geo::Length_t,::geo::Length_t,::geo::Length_t)> Point3D
Atom object for reading a 3D point or vector (centimeters).
Geometry information for a single TPC.
std::vector< pma::Node3D * > const & Nodes(void) const
PMAlgStitching(const pma::PMAlgStitching::Config &config)
std::vector< TrkCandidate > const & tracks(void) const
bool setTreeOriginAtFront(pma::Track3D *trk)
double Length() const
Length is associated with z coordinate [cm].
unsigned int fNodesFromEnd
void StitchTracksCPA(pma::TrkCandidateColl &tracks)
unsigned int BackCryo(void) const
fhicl::Atom< int > StitchingThreshold
int getCandidateIndex(pma::Track3D const *candidate) const
The data type to uniquely identify a TPC.
unsigned int FrontCryo(void) const
void merge(size_t idx1, size_t idx2)
double HalfHeight() const
Height is associated with y coordinate [cm].
Implementation of the Projection Matching Algorithm.
pma::Track3D * GetRoot(void)
double GetOptimalStitchShift(TVector3 &pos1, TVector3 &pos2, TVector3 &dir1, TVector3 &dir2, double &shift)
void StitchTracksAPA(pma::TrkCandidateColl &tracks)
fhicl::Atom< unsigned int > NodesFromEnd
double fStitchingThreshold
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
std::map< geo::TPCID, double > fTPCXOffsetsCPA
std::map< geo::TPCID, double > fTPCXOffsetsAPA
void StitchTracks(pma::TrkCandidateColl &tracks, bool isCPA)
void LocalToWorld(const double *tpc, double *world) const
Transform point from local TPC frame to world frame.
const double * PlaneLocation(unsigned int p) const
Returns the coordinates of the center of the specified plane [cm].
art framework interface to geometry description
double HalfWidth() const
Width is associated with x coordinate [cm].
constexpr Point origin()
Returns a origin position with a point of the specified type.
cet::coded_exception< error, detail::translate > exception
void ApplyDriftShiftInTree(double dx, bool skipFirst=false)
Adjust track tree position in the drift direction (when T0 is being corrected).
Encapsulate the construction of a single detector plane.