PmaTrack3D.h
Go to the documentation of this file.
1 /**
2  * @file PmaTrack3D.h
3  *
4  * @author D.Stefan and R.Sulej
5  *
6  * @brief Implementation of the Projection Matching Algorithm
7  *
8  * Build 3D segments and whole tracks by simultaneous matching hits in 2D projections.
9  * Based on the "Precise 3D track reco..." AHEP (2013) 260820, with all the tricks that we
10  * developed later and with the work for the track-vertex topology optimization done at FNAL.
11  *
12  * Progress:
13  * May-June 2015: basic functionality for single (not-branching) 3D track optimization and dQ/dx.
14  * August 2015: 3D vertex finding and branching tracks optimization.
15  */
16 
17 #ifndef PmaTrack3D_h
18 #define PmaTrack3D_h
19 
20 #include "TVector2.h"
21 #include "TVector3.h"
22 
27 namespace detinfo {
28  class DetectorClocksData;
29  class DetectorPropertiesData;
30 }
31 
32 namespace pma {
33  class Segment3D;
34  class Track3D;
35 }
36 
37 class pma::Track3D {
38 public:
39  enum ETrackEnd { kBegin = -1, kEnd = 1 };
40  enum EDirection { kForward = -1, kBackward = 1 };
41  enum ETag {
43  kTrackLike = 0,
44  kEmLike = 1,
45  kStopping = 2,
46  kCosmic = 4,
47 
48  kGeometry_YY = 0x000100,
49  kGeometry_YZ = 0x000200,
50  kGeometry_ZZ = 0x000300,
51  kGeometry_XX = 0x000400,
52  kGeometry_XY = 0x000500,
53  kGeometry_XZ = 0x000600,
54 
55  kGeometry_Y = 0x001000,
56  kGeometry_Z = 0x002000,
57  kGeometry_X = 0x003000,
58 
61  kBeamIncompatible = 0x030000
62  };
63  ETag
64  GetTag() const noexcept
65  {
66  return fTag;
67  }
68  bool
69  HasTagFlag(ETag value) const noexcept
70  {
71  return (fTag & value);
72  }
73  void
75  {
76  fTag = (ETag)(fTag | value);
77  }
78 
79  Track3D();
80  Track3D(const Track3D& src);
81  ~Track3D();
82 
83  bool Initialize(detinfo::DetectorPropertiesData const& detProp, float initEndSegW = 0.05F);
84 
85  pma::Hit3D* release_at(size_t index);
86  void
88  {
89  hit->fParent = this;
90  fHits.push_back(hit);
91  }
93  bool erase(const art::Ptr<recob::Hit>& hit);
94 
95  pma::Hit3D* operator[](size_t index) { return fHits[index]; }
96  pma::Hit3D const* operator[](size_t index) const { return fHits[index]; }
97  pma::Hit3D const*
98  front() const
99  {
100  return fHits.front();
101  }
102  pma::Hit3D const*
103  back() const
104  {
105  return fHits.back();
106  }
107  size_t
108  size() const
109  {
110  return fHits.size();
111  }
112 
113  int index_of(const pma::Hit3D* hit) const;
114  int index_of(const pma::Node3D* n) const;
115 
116  double
117  Length(size_t step = 1) const
118  {
119  return Length(0, size() - 1, step);
120  }
121  double Length(size_t start, size_t stop, size_t step = 1) const;
122 
123  double Dist2(const TVector2& p2d, unsigned int view, unsigned int tpc, unsigned int cryo) const;
124  double Dist2(const TVector3& p3d) const;
125 
126  /// Get trajectory direction at given hit index.
127  pma::Vector3D GetDirection3D(size_t index) const;
128 
129  /// Add hits; does not update hit->node/seg assignments nor hit projection to
130  /// track, so MakeProjection() and SortHits() should be called as needed.
131  void AddHits(detinfo::DetectorPropertiesData const& detProp,
132  const std::vector<art::Ptr<recob::Hit>>& hits);
133 
134  /// Remove hits; removes also hit->node/seg assignments.
135  void RemoveHits(const std::vector<art::Ptr<recob::Hit>>& hits);
136 
137  unsigned int NHits(unsigned int view) const;
138  unsigned int NEnabledHits(unsigned int view = geo::kUnknown) const;
139  bool HasTwoViews(size_t nmin = 1) const;
140 
141  std::vector<unsigned int> TPCs() const;
142  std::vector<unsigned int> Cryos() const;
143 
144  unsigned int
145  FrontTPC() const
146  {
147  return fNodes.front()->TPC();
148  }
149  unsigned int
150  FrontCryo() const
151  {
152  return fNodes.front()->Cryo();
153  }
154 
155  unsigned int
156  BackTPC() const
157  {
158  return fNodes.back()->TPC();
159  }
160  unsigned int
161  BackCryo() const
162  {
163  return fNodes.back()->Cryo();
164  }
165 
166  bool
167  HasTPC(int tpc) const
168  {
169  for (auto n : fNodes)
170  if (n->TPC() == tpc) return true;
171  return false;
172  }
173 
174  /// Rectangular region of the track 2D projection in view/tpc/cryo; first in
175  /// the returned pair is (min_wire; min_drift), second is (max_wire;
176  /// max_drift). Used for preselection of neighbouring hits in the track
177  /// validation functions.
178  std::pair<TVector2, TVector2> WireDriftRange(detinfo::DetectorPropertiesData const& detProp,
179  unsigned int view,
180  unsigned int tpc,
181  unsigned int cryo) const;
182 
183  /// Invert the order of hits and vertices in the track, break other tracks if
184  /// needed (new tracks are added to the allTracks vector). Returns true if
185  /// successful or false if any of required track flips was not possible (e.g.
186  /// resulting track would be composed of hits from a single 2D projection).
187  bool Flip(const detinfo::DetectorPropertiesData& detProp, std::vector<pma::Track3D*>& allTracks);
188 
189  /// Invert the order of hits and vertices in the track, will fail on
190  /// configuration that causes breaking another track.
191  void Flip();
192 
193  /// Check if the track can be flipped without breaking any other track.
194  bool CanFlip() const;
195 
196  void AutoFlip(pma::Track3D::EDirection dir, double thr = 0.0, unsigned int n = 0);
197  bool AutoFlip(detinfo::DetectorPropertiesData const& detProp,
198  std::vector<pma::Track3D*>& allTracks,
200  double thr = 0.0,
201  unsigned int n = 0);
202 
203  /// MSE of 2D hits.
204  double TestHitsMse(detinfo::DetectorPropertiesData const& detProp,
205  const std::vector<art::Ptr<recob::Hit>>& hits,
206  bool normalized = true) const; // normalize to the number of hits
207 
208  /// Count close 2D hits.
209  unsigned int TestHits(detinfo::DetectorPropertiesData const& detProp,
210  const std::vector<art::Ptr<recob::Hit>>& hits,
211  double dist = 0.4) const; // max acceptable distance [cm]
212 
213  int NextHit(int index, unsigned int view = geo::kZ, bool inclDisabled = false) const;
214  int PrevHit(int index, unsigned int view = geo::kZ, bool inclDisabled = false) const;
215 
216  /// Length of the track part associated with index'th hit. Calculated as a half distance to
217  /// the preceding hit plus half distance to the subsequent hit. In case of the first (last)
218  /// hit - missing part is estimated as 1/4 of the distance to the next (previous) hit.
219  /// NOTE: only hits from a given view are considered; other hits are accounted for
220  /// segment lengths but overall dx is calculated between hits in given view.
221  double HitDxByView(size_t index, unsigned int view) const;
222 
223  /// Sequence of <hit_index, (wire, drift, X, Y, Z, dE, dx, range)> values for the track,
224  /// hits tagged as outliers are skipped by default.
225  /** Results are pushed into the dedx vector given in the function arguments:
226 
227  hit (segment middle if many hits) 2D projection in view:
228  dedx[n][0] = wire;
229  dedx[n][1] = drift;
230 
231  hit (segment middle if many hits) 3D position [cm]:
232  dedx[n][2] = X;
233  dedx[n][3] = Y;
234  dedx[n][4] = Z;
235 
236  dedx[n][5] = dE [now ADC], energy assigned to the segment;
237 
238  dedx[n][6] = dx [cm], length of the segment.
239 
240  dedx[n][7] = range, total length to the track endpoint;
241 
242  Parameters:
243  dedx - vector to store results (empty at the begining);
244  view - view (U, V or Z) from which dedx is created;
245  skip - number of hits to skip at the begining (first hit has poorly estimated segment
246  length so it can be convenient to set skip=1 and handle first hit charge manually);
247  inclDisabled - if true then artificial hits added with CompleteMissingWires() are used,
248  otherwise only true hits found in ADC are used.
249 
250  Return value: sum of ADC's of hits skipped at the begining. */
251  double GetRawdEdxSequence(std::map<size_t, std::vector<double>>& dedx,
252  unsigned int view = geo::kZ,
253  unsigned int skip = 0,
254  bool inclDisabled = false) const;
255 
256  std::vector<float> DriftsOfWireIntersection(detinfo::DetectorPropertiesData const& detProp,
257  unsigned int wire,
258  unsigned int view) const;
259  size_t CompleteMissingWires(detinfo::DetectorPropertiesData const& detProp, unsigned int view);
260 
261  void
262  AddRefPoint(const TVector3& p)
263  {
264  fAssignedPoints.push_back(new TVector3(p));
265  }
266  void
267  AddRefPoint(double x, double y, double z)
268  {
269  fAssignedPoints.push_back(new TVector3(x, y, z));
270  }
271  bool HasRefPoint(TVector3* p) const;
272 
273  /// MSE of hits weighted with hit amplidudes and wire plane coefficients.
274  double GetMse(unsigned int view = geo::kUnknown) const;
275 
276  /// Objective function optimized in track reconstruction.
277  double GetObjFunction(float penaltyFactor = 1.0F) const;
278 
279  /// Main optimization method.
280  double Optimize(const detinfo::DetectorPropertiesData& detProp,
281  int nNodes = -1,
282  double eps = 0.01,
283  bool selAllHits = true,
284  bool setAllNodes = true,
285  size_t selSegHits = 0,
286  size_t selVtxHits = 0);
287 
288  void SortHitsInTree(bool skipFirst = false);
289  void MakeProjectionInTree(bool skipFirst = false);
290  bool UpdateParamsInTree(bool skipFirst, size_t& depth);
291  double GetObjFnInTree(bool skipFirst = false);
292  double TuneSinglePass(bool skipFirst = false);
293  double TuneFullTree(double eps = 0.001, double gmax = 50.0);
294 
295  /// Adjust track tree position in the drift direction (when T0 is being
296  /// corrected).
297  void ApplyDriftShiftInTree(const detinfo::DetectorClocksData& clockData,
298  detinfo::DetectorPropertiesData const& detProp,
299  double dx,
300  bool skipFirst = false);
301  /// Function to convert dx into dT0
302  void SetT0FromDx(const detinfo::DetectorClocksData& clockData,
303  detinfo::DetectorPropertiesData const& detProp,
304  double dx);
305  double
306  GetT0() const
307  {
308  return fT0;
309  }
310  /// Check if the T0 has been set - enables us to distinguish between T0 set
311  /// very close to zero or not set.
312  bool
313  HasT0() const noexcept
314  {
315  return fT0Flag;
316  }
317 
318  /// Cut out tails with no hits assigned.
319  void CleanupTails();
320 
321  /// Move the first/last Node3D to the first/last hit in the track;
322  /// returns true if all OK, false if empty segments found.
323  bool ShiftEndsToHits();
324 
325  std::vector<pma::Segment3D*> const&
326  Segments() const noexcept
327  {
328  return fSegments;
329  }
330 
331  pma::Segment3D* NextSegment(pma::Node3D* vtx) const;
332  pma::Segment3D* PrevSegment(pma::Node3D* vtx) const;
333 
334  std::vector<pma::Node3D*> const&
335  Nodes() const noexcept
336  {
337  return fNodes;
338  }
339  pma::Node3D*
340  FirstElement() const
341  {
342  return fNodes.front();
343  }
344  pma::Node3D*
345  LastElement() const
346  {
347  return fNodes.back();
348  }
349 
350  void AddNode(pma::Node3D* node);
351  void
353  TVector3 const& p3d,
354  unsigned int tpc,
355  unsigned int cryo)
356  {
357  double ds = fNodes.empty() ? 0 : fNodes.back()->GetDriftShift();
358  AddNode(new pma::Node3D(detProp, p3d, tpc, cryo, false, ds));
359  }
360  bool AddNode(detinfo::DetectorPropertiesData const& detProp);
361 
362  void InsertNode(detinfo::DetectorPropertiesData const& detProp,
363  TVector3 const& p3d,
364  size_t at_idx,
365  unsigned int tpc,
366  unsigned int cryo);
367  bool RemoveNode(size_t idx);
368 
370  size_t idx,
371  bool try_start_at_idx = true);
372 
373  bool AttachTo(pma::Node3D* vStart, bool noFlip = false);
374  bool AttachBackTo(pma::Node3D* vStart);
375  bool IsAttachedTo(pma::Track3D const* trk) const;
376 
377  /// Extend the track with everything from src, delete the src;
378  void ExtendWith(pma::Track3D* src);
379 
380  pma::Track3D* GetRoot();
381  bool GetBranches(std::vector<pma::Track3D const*>& branches, bool skipFirst = false) const;
382 
383  void MakeProjection();
384  void UpdateProjection();
385  void SortHits();
386 
387  unsigned int DisableSingleViewEnds();
388  bool SelectHits(float fraction = 1.0F);
389  bool SelectRndHits(size_t segmax, size_t vtxmax);
390  bool SelectAllHits();
391 
392  float
394  {
395  return fEndSegWeight;
396  }
397  void
398  SetEndSegWeight(float value) noexcept
399  {
400  fEndSegWeight = value;
401  }
402 
403  float
404  GetPenalty() const noexcept
405  {
406  return fPenaltyFactor;
407  }
408  void
409  SetPenalty(float value) noexcept
410  {
411  fPenaltyFactor = value;
412  }
413 
414  unsigned int
416  {
417  return fMaxHitsPerSeg;
418  }
419  void
420  SetMaxHitsPerSeg(unsigned int value) noexcept
421  {
422  fMaxHitsPerSeg = value;
423  }
424 
425 private:
426  void ClearNodes();
427  void MakeFastProjection();
428 
429  bool AttachToSameTPC(pma::Node3D* vStart);
430  bool AttachToOtherTPC(pma::Node3D* vStart);
431 
432  bool AttachBackToSameTPC(pma::Node3D* vStart);
433  bool AttachBackToOtherTPC(pma::Node3D* vStart);
434 
435  void InternalFlip(std::vector<pma::Track3D*>& toSort);
436 
437  void UpdateHitsRadius();
438  double AverageDist2() const;
439 
440  bool InitFromHits(detinfo::DetectorPropertiesData const& detProp,
441  int tpc,
442  int cryo,
443  float initEndSegW = 0.05F);
444  bool InitFromRefPoints(detinfo::DetectorPropertiesData const& detProp, int tpc, int cryo);
445  void InitFromMiddle(detinfo::DetectorPropertiesData const& detProp, int tpc, int cryo);
446 
447  pma::Track3D* GetNearestTrkInTree(const TVector3& p3d_cm, double& dist, bool skipFirst = false);
448  pma::Track3D* GetNearestTrkInTree(const TVector2& p2d_cm,
449  unsigned int view,
450  unsigned int tpc,
451  unsigned int cryo,
452  double& dist,
453  bool skipFirst = false);
454  void ReassignHitsInTree(pma::Track3D* plRoot = nullptr);
455 
456  /// Distance to the nearest subsequent (dir = Track3D::kForward) or preceeding
457  /// (dir = Track3D::kBackward) hit in given view. In case of last (first) hit
458  /// in this view the half-distance in opposite direction is returned.
459  /// Parameter secondDir is only for internal protection - please leave the
460  /// default value.
461  double HitDxByView(size_t index,
462  unsigned int view,
464  bool secondDir = false) const;
465 
466  /// Calculate 3D position corresponding to 2D hit, return true if the 3D point
467  /// is in the same TPC as the hit, false otherwise. Calculates also distance^2
468  /// between the hit and 2D projection of the track. NOTE: results are
469  /// meaningful only if the function returns true.
470  bool GetUnconstrainedProj3D(detinfo::DetectorPropertiesData const& detProp,
472  TVector3& p3d,
473  double& dist2) const;
474 
475  void DeleteSegments();
476  void RebuildSegments();
477  bool SwapVertices(size_t v0, size_t v1);
478  bool UpdateParams();
479 
480  bool CheckEndSegment(pma::Track3D::ETrackEnd endCode);
481 
482  std::vector<pma::Hit3D*> fHits;
483 
484  std::vector<TVector3*> fAssignedPoints;
485 
486  pma::Element3D* GetNearestElement(const TVector2& p2d,
487  unsigned int view,
488  int tpc = -1,
489  bool skipFrontVtx = false,
490  bool skipBackVtx = false) const;
491  pma::Element3D* GetNearestElement(const TVector3& p3d) const;
492 
493  std::vector<pma::Node3D*> fNodes;
494  std::vector<pma::Segment3D*> fSegments;
495 
496  unsigned int fMaxHitsPerSeg{70};
497  float fPenaltyFactor{1.0F};
498  float fMaxSegStopFactor{8.0F};
499 
500  unsigned int fSegStopValue{2};
501  unsigned int fMinSegStop{2};
502  unsigned int fMaxSegStop{2};
503 
504  float fSegStopFactor{0.2F};
505  float fPenaltyValue{0.1F};
506  float fEndSegWeight{0.05F};
507  float fHitsRadius{1.0F};
508 
509  double fT0{};
510  bool fT0Flag{false};
511 
513 };
514 
515 #endif
float Length(const PFPStruct &pfp)
Definition: PFPUtils.cxx:3303
bool HasTPC(int tpc) const
Definition: PmaTrack3D.h:167
void SetTagFlag(ETag value)
Definition: PmaTrack3D.h:74
void AddNode(detinfo::DetectorPropertiesData const &detProp, TVector3 const &p3d, unsigned int tpc, unsigned int cryo)
Definition: PmaTrack3D.h:352
G4double thr[100]
Definition: G4S2Light.cc:59
pma::Track3D * fParent
Definition: PmaHit3D.h:199
double Dist2(const TVector2 &v1, const TVector2 &v2)
Definition: Utilities.cxx:37
void AddHits(TCSlice &slc, Trajectory &tj, unsigned short ipt, bool &sigOK)
Definition: StepUtils.cxx:1037
pma::Hit3D * operator[](size_t index)
Definition: PmaTrack3D.h:95
Unknown view.
Definition: geo_types.h:136
pma::Hit3D const * front() const
Definition: PmaTrack3D.h:98
struct vector vector
Planes which measure Z direction.
Definition: geo_types.h:132
Implementation of the Projection Matching Algorithm.
void AddRefPoint(double x, double y, double z)
Definition: PmaTrack3D.h:267
string dir
std::vector< pma::Segment3D * > fSegments
Definition: PmaTrack3D.h:494
unsigned int BackTPC() const
Definition: PmaTrack3D.h:156
float GetPenalty() const noexcept
Definition: PmaTrack3D.h:404
bool SortHits(HitLoc const &h1, HitLoc const &h2)
recob::tracking::Vector_t Vector3D
Definition: Utilities.h:31
void AddRefPoint(const TVector3 &p)
Definition: PmaTrack3D.h:262
int TPC(void) const
TPC index or -1 if out of any TPC.
Definition: PmaElement3D.h:34
unsigned int BackCryo() const
Definition: PmaTrack3D.h:161
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
unsigned int GetMaxHitsPerSeg() const noexcept
Definition: PmaTrack3D.h:415
void SetMaxHitsPerSeg(unsigned int value) noexcept
Definition: PmaTrack3D.h:420
double GetT0() const
Definition: PmaTrack3D.h:306
float GetEndSegWeight() const noexcept
Definition: PmaTrack3D.h:393
fInnerVessel push_back(Point(-578.400000, 0.000000, 0.000000))
pma::Node3D * FirstElement() const
Definition: PmaTrack3D.h:340
pma::Node3D * LastElement() const
Definition: PmaTrack3D.h:345
std::void_t< T > n
bool HasTagFlag(ETag value) const noexcept
Definition: PmaTrack3D.h:69
void SetEndSegWeight(float value) noexcept
Definition: PmaTrack3D.h:398
std::vector< pma::Segment3D * > const & Segments() const noexcept
Definition: PmaTrack3D.h:326
p
Definition: test.py:223
void Initialize(void)
Implementation of the Projection Matching Algorithm.
unsigned int FrontTPC() const
Definition: PmaTrack3D.h:145
unsigned int FrontCryo() const
Definition: PmaTrack3D.h:150
General LArSoft Utilities.
ETag GetTag() const noexcept
Definition: PmaTrack3D.h:64
Definition of data types for geometry description.
std::vector< pma::Node3D * > fNodes
Definition: PmaTrack3D.h:493
Detector simulation of raw signals on wires.
void push_back(pma::Hit3D *hit)
Definition: PmaTrack3D.h:87
Implementation of the Projection Matching Algorithm.
double Length(size_t step=1) const
Definition: PmaTrack3D.h:117
vector< string > Split(string input, string delim)
Definition: StringUtils.cxx:36
Contains all timing reference information for the detector.
constexpr double dist(const TReal *x, const TReal *y, const unsigned int dimension)
std::vector< TVector3 * > fAssignedPoints
Definition: PmaTrack3D.h:484
bool HasT0() const noexcept
Definition: PmaTrack3D.h:313
const unsigned int kCosmic
Definition: TriggerTypes.h:20
pma::Hit3D const * back() const
Definition: PmaTrack3D.h:103
void SetPenalty(float value) noexcept
Definition: PmaTrack3D.h:409
list x
Definition: train.py:276
pma::Hit3D const * operator[](size_t index) const
Definition: PmaTrack3D.h:96
std::vector< pma::Node3D * > const & Nodes() const noexcept
Definition: PmaTrack3D.h:335
size_t size() const
Definition: PmaTrack3D.h:108
std::vector< pma::Hit3D * > fHits
Definition: PmaTrack3D.h:482