15 #include "messagefacility/MessageLogger/MessageLogger.h"
37 mf::LogInfo(
"pma::PMAlgStitching") <<
"Passed " << tracks.
size() <<
" tracks for CPA stitching.";
38 StitchTracks(clockData, detProp, tracks,
true);
47 mf::LogInfo(
"pma::PMAlgStitching") <<
"Passed " << tracks.
size() <<
" tracks for APA stitching.";
48 StitchTracks(clockData, detProp, tracks,
false);
61 unsigned int minTrkLength = 2 * fNodesFromEnd + 3;
63 if (minTrkLength < 6) minTrkLength = 6;
67 while (t < tracks.
size()) {
70 if (t1->
Nodes().size() < minTrkLength) {
79 TVector3 trk1Front = t1->
Nodes()[(fNodesFromEnd)]->
Point3D();
80 TVector3 trk1Back = t1->
Nodes()[t1->
Nodes().size() - 1 - fNodesFromEnd]->Point3D();
81 TVector3 trk1FrontDir = (trk1Front - t1->
Nodes()[(fNodesFromEnd + 1)]->
Point3D()).Unit();
82 TVector3 trk1BackDir =
83 (trk1Back - t1->
Nodes()[t1->
Nodes().size() - 1 - (fNodesFromEnd + 1)]->
Point3D()).Unit();
87 double offsetBack1 = GetTPCOffset(t1->
BackTPC(), t1->
BackCryo(), isCPA);
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;
103 TVector3 trk2Front = t2->
Nodes()[(fNodesFromEnd)]->
Point3D();
104 TVector3 trk2Back = t2->
Nodes()[t2->
Nodes().size() - 1 - fNodesFromEnd]->Point3D();
105 TVector3 trk2FrontDir = (trk2Front - t2->
Nodes()[(fNodesFromEnd + 1)]->
Point3D()).Unit();
106 TVector3 trk2BackDir =
107 (trk2Back - t2->
Nodes()[t2->
Nodes().size() - 1 - (fNodesFromEnd + 1)]->
Point3D()).Unit();
111 double offsetBack2 = GetTPCOffset(t2->
BackTPC(), t2->
BackCryo(), isCPA);
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; }
180 score = GetOptimalStitchShift(t1Pos, t2Pos, t1Dir, t2Dir, xShift1);
182 if (score < fStitchingThreshold && score < bestMatchScore) {
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;
195 mf::LogInfo(
"pma::PMAlgStitcher")
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
202 <<
", " << t1->
BackTPC() << std::endl
204 <<
", " << t2->
BackTPC() << std::endl
205 <<
" - " << isBestFront1 <<
" :: " << isBestFront2 << std::endl;
211 if (bestTrkMatch != 0x0) {
215 bool reverse =
false;
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)) {
234 throw cet::exception(
"pma::PMAlgStitching")
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);
283 mf::LogWarning(
"pma::PMAlgStitching") <<
" could not merge.";
290 tracks.
merge((
size_t)idx1, (
size_t)idx2);
293 mf::LogWarning(
"pma::PMAlgStitching") <<
" could not merge.";
297 mf::LogInfo(
"pma::PMAlgStitching") <<
"...done";
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);
329 double thisScore = GetTrackPairDelta(newPos1, newPos2, dir1, dir2);
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; }
389 fTPCXOffsetsAPA.insert(std::make_pair(tID, xAnode));
394 double center[3] = {0.};
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; }
405 fTPCXOffsetsCPA.insert(std::make_pair(tID, xCathode));
416 if (isCPA) { offset = fTPCXOffsetsCPA[thisTPCID]; }
418 offset = fTPCXOffsetsAPA[thisTPCID];
bool HasPlane(unsigned int iplane) const
Returns whether a plane with index iplane is present in this TPC.
BEGIN_PROLOG TPC Trig offset(g4 rise time) ProjectToHeight
Utilities related to art service access.
double GetTPCOffset(unsigned int tpc, unsigned int cryo, bool isCPA)
ClusterModuleLabel join with tracks
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)
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.
BEGIN_PROLOG or score(default)}sbnd_crttrackmatchingalg_crID
PMAlgStitching(const pma::PMAlgStitching::Config &config)
std::vector< pma::Node3D * > const & Nodes() const noexcept
Implementation of the Projection Matching Algorithm.
double GetTrackPairDelta(TVector3 &pos1, TVector3 &pos2, TVector3 &dir1, TVector3 &dir2) const
unsigned int BackTPC() const
double Length() const
Length is associated with z coordinate [cm].
unsigned int fNodesFromEnd
process_name pandoraGausCryo1 vertexChargeCryo1 vertexStubCryo1 xmin
unsigned int BackCryo() const
Access the description of detector geometry.
double GetOptimalStitchShift(TVector3 &pos1, TVector3 &pos2, TVector3 &dir1, TVector3 &dir2, double &shift) const
bool setTreeOriginAtFront(detinfo::DetectorPropertiesData const &detProp, pma::Track3D *trk)
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)
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
art framework interface to geometry description
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.
Encapsulate the construction of a single detector plane.