37 mf::LogInfo(
"pma::PMAlgStitching") <<
"Passed " << tracks.
size() <<
" tracks for CPA stitching.";
46 mf::LogInfo(
"pma::PMAlgStitching") <<
"Passed " << tracks.
size() <<
" tracks for APA stitching.";
61 if (minTrkLength < 6) minTrkLength = 6;
65 while (t < tracks.
size()) {
68 if (t1->
Nodes().size() < minTrkLength) {
80 TVector3 trk1BackDir =
87 bool isBestFront1 =
false;
88 bool isBestFront2 =
false;
89 double xBestShift = 0;
90 double frontShift1 = t1->
Nodes()[0]->Point3D().X() - offsetFront1;
91 double backShift1 = t1->
Nodes()[t1->
Nodes().size() - 1]->Point3D().X() - offsetBack1;
93 double bestMatchScore = 99999;
95 for (
unsigned int u = t + 1; u < tracks.
size(); ++u) {
98 if (t2->
Nodes().size() < minTrkLength)
continue;
104 TVector3 trk2BackDir =
119 if (tpc1 == tpc2) giveUp =
true;
122 if (tpc1 == tpc2) giveUp =
true;
126 if (tpc1 == tpc2) giveUp =
true;
129 if (tpc1 == tpc2) giveUp =
true;
132 if (giveUp)
continue;
135 double surfaceGap = 10.0;
136 bool carryOn[4] = {
true,
true,
true,
true};
137 if (fabs(offsetFront1 - offsetFront2) > surfaceGap) carryOn[0] =
false;
138 if (fabs(offsetFront1 - offsetBack2) > surfaceGap) carryOn[1] =
false;
139 if (fabs(offsetBack1 - offsetFront2) > surfaceGap) carryOn[2] =
false;
140 if (fabs(offsetBack1 - offsetBack2) > surfaceGap) carryOn[3] =
false;
143 for (
int i = 0; i < 4; ++i) {
145 if (!carryOn[i])
continue;
154 t1Dir = trk1FrontDir;
155 xShift1 = frontShift1;
160 xShift1 = backShift1;
164 t2Dir = trk2FrontDir;
172 if (t1Dir.X() * t2Dir.X() > 0) {
continue; }
179 xBestShift = xShift1;
180 bestMatchScore = score;
181 if (i < 2) { isBestFront1 =
true; }
183 isBestFront1 =
false;
185 if (i % 2 == 0) { isBestFront2 =
true; }
187 isBestFront2 =
false;
190 <<
"Tracks " << t <<
" and " << u <<
" matching score = " << score << std::endl
191 <<
" - " << t1Pos.X() <<
", " << t1Pos.Y() <<
", " << t1Pos.Z() <<
" :: " << t1Dir.X()
192 <<
", " << t1Dir.Y() <<
", " << t1Dir.Z() << std::endl
193 <<
" - " << t2Pos.X() <<
", " << t2Pos.Y() <<
", " << t2Pos.Z() <<
" :: " << t2Dir.X()
194 <<
", " << t2Dir.Y() <<
", " << t2Dir.Z() << std::endl
196 <<
", " << t1->
BackTPC() << std::endl
198 <<
", " << t2->
BackTPC() << std::endl
199 <<
" - " << isBestFront1 <<
" :: " << isBestFront2 << std::endl;
205 if (bestTrkMatch != 0x0) {
209 bool reverse =
false;
212 if (isBestFront1 && isBestFront2) { flip1 =
true; }
214 else if (isBestFront1 && !isBestFront2) {
218 else if (!isBestFront1 && !isBestFront2) {
226 bool canMerge =
true;
227 if ((tid1 < 0) || (tid2 < 0)) {
229 <<
"Track not found in the collection." << std::endl;
233 std::vector<pma::Track3D*> newTracks;
234 if (t1->
Flip(detProp, newTracks)) {
235 mf::LogInfo(
"pma::PMAlgStitching") <<
"Track 1 flipped.";
238 mf::LogInfo(
"pma::PMAlgStitching") <<
"Unable to flip Track 1.";
241 for (
const auto ts : newTracks) {
243 tracks.
tracks().emplace_back(ts, -1, tid1);
248 std::vector<pma::Track3D*> newTracks;
249 if (bestTrkMatch->
Flip(detProp, newTracks)) {
250 mf::LogInfo(
"pma::PMAlgStitching") <<
"Track 2 flipped.";
253 mf::LogInfo(
"pma::PMAlgStitching") <<
"Unable to flip Track 1.";
256 for (
const auto ts : newTracks) {
258 tracks.
tracks().emplace_back(ts, -1, tid2);
266 mf::LogInfo(
"pma::PMAlgStitching") <<
"Merging tracks...";
273 tracks.
merge((
size_t)idx2, (
size_t)idx1);
284 tracks.
merge((
size_t)idx1, (
size_t)idx2);
311 double stepSize = 0.1;
312 double minShift = shift - (50. * stepSize);
313 double maxShift = shift + (50. * stepSize);
314 double bestShift = 99999;
315 double bestScore = 99999;
317 for (shift = minShift; shift <= maxShift; shift += stepSize) {
318 TVector3 newPos1 = pos1;
319 TVector3 newPos2 = pos2;
320 newPos1.SetX(pos1.X() - shift);
321 newPos2.SetX(pos2.X() + shift);
323 if (thisScore < bestScore) {
325 bestScore = thisScore;
337 TVector3& dir2)
const 340 double delta = -999.;
343 double steps1 = (pos2.X() - pos1.X()) / dir1.X();
344 double steps2 = (pos1.X() - pos2.X()) / dir2.X();
347 TVector3 trk1Merge = pos1 + steps1 * dir1;
348 TVector3 trk2Merge = pos2 + steps2 * dir2;
351 delta = (trk1Merge - pos2).Mag() + (trk2Merge - pos1).Mag();
359 auto const* geom = lar::providerFrom<geo::Geometry>();
364 auto const& tID = aTPC.ID();
368 unsigned int plane = 0;
369 bool hasPlane =
false;
370 for (; plane < 4; ++plane) {
371 hasPlane = wireReadoutGeom.HasPlane({tID, plane});
372 if (hasPlane) {
break; }
375 if (!hasPlane) {
continue; }
378 double xAnode = wireReadoutGeom.FirstPlane(tID).GetCenter().X();
383 auto const center = aTPC.GetCenter();
384 double tpcDim[3] = {aTPC.HalfWidth(), aTPC.HalfHeight(), 0.5 * aTPC.Length()};
385 double xmin = center.X() - tpcDim[0];
386 double xmax = center.X() + tpcDim[0];
387 double xCathode = 0.;
389 if (fabs(xmin - xAnode) > fabs(xmax - xAnode)) { xCathode = xmin; }
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.
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.
cout<< "Opened file "<< fin<< " ixs= "<< ixs<< endl;if(ixs==0) hhh=(TH1F *) fff-> Get("h1")
double GetTrackPairDelta(TVector3 &pos1, TVector3 &pos2, TVector3 &dir1, TVector3 &dir2) const
unsigned int BackTPC() const
std::map< geo::TPCID, double > fTPCXOffsetsAPA
unsigned int fNodesFromEnd
unsigned int BackCryo() const
Access the description of the physical detector geometry.
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.
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.
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
std::vector< TrkCandidate > const & tracks() const
cet::coded_exception< error, detail::translate > exception
Encapsulate the construction of a single detector plane .