37 mf::LogInfo(
"pma::PMAlgStitching") <<
"Passed " << tracks.
size() <<
" tracks for CPA stitching.";
47 mf::LogInfo(
"pma::PMAlgStitching") <<
"Passed " << tracks.
size() <<
" tracks for APA stitching.";
63 if (minTrkLength < 6) minTrkLength = 6;
67 while (t < tracks.
size()) {
70 if (t1->
Nodes().size() < minTrkLength) {
82 TVector3 trk1BackDir =
89 bool isBestFront1 =
false;
90 bool isBestFront2 =
false;
91 double xBestShift = 0;
92 double frontShift1 = t1->
Nodes()[0]->Point3D().X() - offsetFront1;
93 double backShift1 = t1->
Nodes()[t1->
Nodes().size() - 1]->Point3D().X() - offsetBack1;
95 double bestMatchScore = 99999;
97 for (
unsigned int u = t + 1; u < tracks.
size(); ++u) {
100 if (t2->
Nodes().size() < minTrkLength)
continue;
106 TVector3 trk2BackDir =
121 if (tpc1 == tpc2) giveUp =
true;
124 if (tpc1 == tpc2) giveUp =
true;
128 if (tpc1 == tpc2) giveUp =
true;
131 if (tpc1 == tpc2) giveUp =
true;
134 if (giveUp)
continue;
137 double surfaceGap = 10.0;
138 bool carryOn[4] = {
true,
true,
true,
true};
139 if (fabs(offsetFront1 - offsetFront2) > surfaceGap) carryOn[0] =
false;
140 if (fabs(offsetFront1 - offsetBack2) > surfaceGap) carryOn[1] =
false;
141 if (fabs(offsetBack1 - offsetFront2) > surfaceGap) carryOn[2] =
false;
142 if (fabs(offsetBack1 - offsetBack2) > surfaceGap) carryOn[3] =
false;
145 for (
int i = 0; i < 4; ++i) {
147 if (!carryOn[i])
continue;
156 t1Dir = trk1FrontDir;
157 xShift1 = frontShift1;
162 xShift1 = backShift1;
166 t2Dir = trk2FrontDir;
174 if (t1Dir.X() * t2Dir.X() > 0) {
continue; }
185 xBestShift = xShift1;
186 bestMatchScore =
score;
187 if (i < 2) { isBestFront1 =
true; }
189 isBestFront1 =
false;
191 if (i % 2 == 0) { isBestFront2 =
true; }
193 isBestFront2 =
false;
196 <<
"Tracks " << t <<
" and " << u <<
" matching score = " << score <<
std::endl 197 <<
" - " << t1Pos.X() <<
", " << t1Pos.Y() <<
", " << t1Pos.Z() <<
" :: " << t1Dir.X()
198 <<
", " << t1Dir.Y() <<
", " << t1Dir.Z() <<
std::endl 199 <<
" - " << t2Pos.X() <<
", " << t2Pos.Y() <<
", " << t2Pos.Z() <<
" :: " << t2Dir.X()
200 <<
", " << t2Dir.Y() <<
", " << t2Dir.Z() <<
std::endl 205 <<
" - " << isBestFront1 <<
" :: " << isBestFront2 <<
std::endl;
211 if (bestTrkMatch != 0x0) {
218 if (isBestFront1 && isBestFront2) { flip1 =
true; }
220 else if (isBestFront1 && !isBestFront2) {
224 else if (!isBestFront1 && !isBestFront2) {
232 bool canMerge =
true;
233 if ((tid1 < 0) || (tid2 < 0)) {
235 <<
"Track not found in the collection." <<
std::endl;
239 std::vector<pma::Track3D*> newTracks;
240 if (t1->
Flip(detProp, newTracks)) {
241 mf::LogInfo(
"pma::PMAlgStitching") <<
"Track 1 flipped.";
244 mf::LogInfo(
"pma::PMAlgStitching") <<
"Unable to flip Track 1.";
247 for (
const auto ts : newTracks) {
249 tracks.
tracks().emplace_back(ts, -1, tid1);
254 std::vector<pma::Track3D*> newTracks;
255 if (bestTrkMatch->
Flip(detProp, newTracks)) {
256 mf::LogInfo(
"pma::PMAlgStitching") <<
"Track 2 flipped.";
259 mf::LogInfo(
"pma::PMAlgStitching") <<
"Unable to flip Track 1.";
262 for (
const auto ts : newTracks) {
264 tracks.
tracks().emplace_back(ts, -1, tid2);
272 mf::LogInfo(
"pma::PMAlgStitching") <<
"Merging tracks...";
280 tracks.
merge((
size_t)idx2, (
size_t)idx1);
290 tracks.
merge((
size_t)idx1, (
size_t)idx2);
318 double stepSize = 0.1;
319 double minShift = shift - (50. * stepSize);
320 double maxShift = shift + (50. * stepSize);
321 double bestShift = 99999;
322 double bestScore = 99999;
324 for (shift = minShift; shift <= maxShift; shift += stepSize) {
325 TVector3 newPos1 = pos1;
326 TVector3 newPos2 = pos2;
327 newPos1.SetX(pos1.X() - shift);
328 newPos2.SetX(pos2.X() + shift);
330 if (thisScore < bestScore) {
332 bestScore = thisScore;
345 TVector3& dir2)
const 348 double delta = -999.;
351 double steps1 = (pos2.X() - pos1.X()) / dir1.X();
352 double steps2 = (pos1.X() - pos2.X()) / dir2.X();
355 TVector3 trk1Merge = pos1 + steps1 * dir1;
356 TVector3 trk2Merge = pos2 + steps2 * dir2;
359 delta = (trk1Merge - pos2).Mag() + (trk2Merge - pos1).Mag();
370 auto const* geom = lar::providerFrom<geo::Geometry>();
373 for (
geo::TPCID const& tID : geom->IterateTPCIDs()) {
378 unsigned int plane = 0;
379 bool hasPlane =
false;
380 for (; plane < 4; ++plane) {
382 if (hasPlane) {
break; }
385 if (!hasPlane) {
continue; }
397 double xmin = center[0] - tpcDim[0];
398 double xmax = center[0] + tpcDim[0];
399 double xCathode = 0.;
401 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.
double GetTPCOffset(unsigned int tpc, unsigned int cryo, bool isCPA)
int getCandidateTreeId(pma::Track3D const *candidate) const
Implementation of the Projection Matching Algorithm.
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)
::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.
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
art framework interface to geometry description
double Length() const
Length is associated with z coordinate [cm].
unsigned int fNodesFromEnd
unsigned int BackCryo() const
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
static unsigned int reverse(QString &chars, unsigned char *level, unsigned int a, unsigned int b)
double fStitchingThreshold
void StitchTracksAPA(const detinfo::DetectorClocksData &clockData, const detinfo::DetectorPropertiesData &detProp, pma::TrkCandidateColl &tracks)
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
Access the description of detector geometry.
std::vector< pma::Node3D * > const & Nodes() const noexcept
IDparameter< geo::TPCID > TPCID
Member type of validated geo::TPCID parameter.
bool Flip(const detinfo::DetectorPropertiesData &detProp, std::vector< pma::Track3D * > &allTracks)
void StitchTracksCPA(const detinfo::DetectorClocksData &clockData, const detinfo::DetectorPropertiesData &detProp, pma::TrkCandidateColl &tracks)
void LocalToWorld(const double *tpc, double *world) const
Transform point from local TPC frame to world frame.
const double * PlaneLocation(unsigned int p) const
double HalfWidth() const
Width is associated with x coordinate [cm].
std::vector< TrkCandidate > const & tracks() const
constexpr Point origin()
Returns a origin position with a point of the specified type.
cet::coded_exception< error, detail::translate > exception
QTextStream & endl(QTextStream &s)
Encapsulate the construction of a single detector plane.