ATTPCROOT  0.3.0-alpha
A ROOT-based framework for analyzing data from active target detectors
AtFitter.cxx
Go to the documentation of this file.
1 #include "AtFitter.h"
2 
3 #include "AtHit.h"
4 #include "AtHitCluster.h" // for AtHitCluster
5 #include "AtTrack.h"
6 
7 #include <Math/Point3D.h> // for Cartesian3D, operator-, PositionVector3D
8 #include <Math/Vector3D.h> // for DisplacementVector3D
9 #include <TMath.h>
10 
11 #include <algorithm>
12 #include <cmath> // for sqrt
13 #include <iostream> // for operator<<, basic_ostream::operator<<
14 #include <memory> // for shared_ptr, __shared_ptr_access, __sha...
15 #include <utility> // for pair
16 
17 constexpr auto cRED = "\033[1;31m";
18 constexpr auto cYELLOW = "\033[1;33m";
19 constexpr auto cNORMAL = "\033[0m";
20 constexpr auto cGREEN = "\033[1;32m";
21 
23 
25 
27 
28 std::tuple<Double_t, Double_t> AtFITTER::AtFitter::GetMomFromBrho(Double_t M, Double_t Z, Double_t brho)
29 {
30 
31  const Double_t M_Ener = M * 931.49401 / 1000.0;
32  Double_t p = brho * Z * (2.99792458 / 10.0); // In GeV
33  Double_t E = TMath::Sqrt(TMath::Power(p, 2) + TMath::Power(M_Ener, 2)) - M_Ener;
34  // std::cout << " Brho : " << brho << " - p : " << p << " - E : " << E << "\n";
35  return std::make_tuple(p, E);
36 }
37 
39 {
40  // Determination of first hit distance. NB: Assuming both tracks have the same angle sign
41  Double_t vertexA = 0.0;
42  Double_t vertexB = 0.0;
43  if (trA->GetGeoTheta() * TMath::RadToDeg() < 90) {
44  auto iniClusterA = trA->GetHitClusterArray()->back();
45  auto iniClusterB = trB->GetHitClusterArray()->back();
46  vertexA = 1000.0 - iniClusterA.GetPosition().Z();
47  vertexB = 1000.0 - iniClusterB.GetPosition().Z();
48  } else if (trA->GetGeoTheta() * TMath::RadToDeg() > 90) {
49  auto iniClusterA = trA->GetHitClusterArray()->front();
50  auto iniClusterB = trB->GetHitClusterArray()->front();
51  vertexA = iniClusterA.GetPosition().Z();
52  vertexB = iniClusterB.GetPosition().Z();
53  }
54 
55  return vertexA < vertexB;
56 }
57 
58 Bool_t AtFITTER::AtFitter::MergeTracks(std::vector<AtTrack *> *trackCandSource, std::vector<AtTrack> *trackDest,
59  Bool_t enableSingleVertexTrack, Double_t clusterRadius, Double_t clusterDistance)
60 {
61 
62  Bool_t toMerge = kFALSE;
63 
64  Int_t addHitCnt = 0;
65  // Find the track closer to vertex
66  std::sort(trackCandSource->begin(), trackCandSource->end(),
67  [this](AtTrack *trA, AtTrack *trB) { return FindVertexTrack(trA, trB); });
68 
69  // Track stitching from vertex
70  AtTrack *vertexTrack = *trackCandSource->begin();
71 
72  if (enableSingleVertexTrack) {
73 
74  // Mark all tracks as merged
75  for (auto track : *trackCandSource)
76  track->SetIsMerged(kTRUE);
77 
78  trackDest->push_back(*vertexTrack);
79  return true;
80  }
81 
82  // Check if the candidate vertex track was merged
83  if (vertexTrack->GetIsMerged())
84  return kFALSE;
85  else
86  vertexTrack->SetIsMerged(kTRUE);
87 
88  // If enabled, choose only the track closest to vertex (i.e. first one of the collection of candidates)
89  // TODO: Select by number of points
90 
91  for (auto it = trackCandSource->begin() + 1; it != trackCandSource->end(); ++it) {
92  // NB: These tracks were previously marked to merge. If merging fails they should be discarded.
93  AtTrack *trackToMerge = *(it);
94  toMerge = kFALSE;
95 
96  // Skip trackes flagged as merged
97  if (!trackToMerge->GetIsMerged()) {
98  trackToMerge->SetIsMerged(kTRUE);
99  } else
100  continue;
101 
102  Double_t endVertexZ = 0.0;
103  Double_t iniMergeZ = 0.0;
104  std::cout << " Trying to merge ... "
105  << "\n";
106  std::cout << " Vertex track " << vertexTrack->GetTrackID() << " - Track to Merge " << trackToMerge->GetTrackID()
107  << "\n";
108  // Check relative position between end and begin of each track using Hit Clusters
109  std::cout << " Vertex angle " << vertexTrack->GetGeoTheta() * TMath::RadToDeg() << "\n";
110  if (vertexTrack->GetGeoTheta() * TMath::RadToDeg() < 90) {
111  auto endClusterVertex = vertexTrack->GetHitClusterArray()->front();
112  auto iniClusterMerge = trackToMerge->GetHitClusterArray()->back();
113  // Check separation and relative distance
114  endVertexZ = 1000.0 - endClusterVertex.GetPosition().Z();
115  iniMergeZ = 1000.0 - iniClusterMerge.GetPosition().Z();
116 
117  Double_t distance = std::sqrt((iniClusterMerge.GetPosition() - endClusterVertex.GetPosition()).Mag2());
118  // std::cout << " Distance between tracks " << distance << "\n";
119  // std::cout << " Ini Merge " << iniMergeZ << " - endVertexZ " << endVertexZ << "\n";
120  if (((iniMergeZ + 10.0) > endVertexZ) && distance < 200) {
121  toMerge = kTRUE;
122  }
123 
124  } else if (vertexTrack->GetGeoTheta() * TMath::RadToDeg() > 90) {
125  auto endClusterVertex = vertexTrack->GetHitClusterArray()->back();
126  auto iniClusterMerge = trackToMerge->GetHitClusterArray()->front();
127  // Check separation and relative distance
128  endVertexZ = endClusterVertex.GetPosition().Z();
129  iniMergeZ = iniClusterMerge.GetPosition().Z();
130  Double_t distance = std::sqrt((iniClusterMerge.GetPosition() - endClusterVertex.GetPosition()).Mag2());
131  // std::cout<<" Distance between tracks "<<distance<<"\n";
132  // std::cout<<" Ini Merge "<<iniMergeZ<<" - endVertexZ "<<endVertexZ<<"\n";
133  if (((iniMergeZ + 10.0) > endVertexZ) &&
134  distance < 100) { // NB: Distance between parts of the backward tracks is more critical
135  toMerge = kTRUE;
136  }
137  }
138 
139  if (toMerge) {
140 
141  std::cout << " --- Merging Succeeded! Vertex track " << vertexTrack->GetTrackID() << " - Track to Merge "
142  << trackToMerge->GetTrackID() << "\n";
143  for (const auto &hit : trackToMerge->GetHitArray()) {
144 
145  vertexTrack->AddHit(hit->Clone()); // TODO: Look at code and see if this can be a move instead of a copy
146  ++addHitCnt;
147  }
148 
149  // Reclusterize after merging
150  vertexTrack->SortHitArrayTime();
151  vertexTrack->ResetHitClusterArray();
152  fTrackTransformer->ClusterizeSmooth3D(
153  *vertexTrack, clusterRadius,
154  clusterDistance); // NB: It can be removed if we force reclusterization for any track in the mina program
155 
156  // TODO: Check if phi recalculatio is needed
157 
158  } else {
159  std::cout << " --- Merging Failed ! Vertex track " << vertexTrack->GetTrackID() << " - Track to Merge "
160  << trackToMerge->GetTrackID() << "\n";
161  }
162  }
163 
164  trackDest->push_back(*vertexTrack);
165 
166  return toMerge;
167 }
168 [[deprecated]] void
169 AtFITTER::AtFitter::MergeTracks(std::vector<AtTrack> *trackCandSource, std::vector<AtTrack> *trackJunkSource,
170  std::vector<AtTrack> *trackDest, bool fitDirection, bool simulationConv)
171 {
172  // DEPRECATED
173  // Track destination are the merged tracks.
174  // Track candidate source are the main tracks identified as candidates.
175  // Track junk source are the tracks from which clusters will be extracted. Boundary conditions are applied: Proximity
176  // in space, angle and center.
177  // NB: Only works for backward tracks
178 
179  Double_t trackDist = 20.0; // Distance between clusters in mm
180  Double_t angleSpread = 5.0; // Maximum angular spread between clusters
181  Double_t centerSpread = 20.0; // Maximim distance between track centers for merging.
182  Int_t minClusters = 3;
183  Int_t trackSize = 0;
184 
185  for (auto trackCand : *trackCandSource) {
186  Double_t thetaCand = trackCand.GetGeoTheta();
187  auto &hitArrayCand = trackCand.GetHitArray();
188  std::pair<Double_t, Double_t> centerCand = trackCand.GetGeoCenter();
189 
190  AtTrack track = trackCand;
191  Int_t jnkCnt = 0;
192  Int_t jnkHitCnt = 0;
193 
194  if (simulationConv) {
195  thetaCand = 180.0 - thetaCand * TMath::RadToDeg();
196 
197  } else {
198  thetaCand = thetaCand * TMath::RadToDeg();
199  }
200 
201  for (auto trackJunk : *trackJunkSource) {
202  Double_t thetaJunk = trackJunk.GetGeoTheta();
203  auto &hitArrayJunk = trackJunk.GetHitArray();
204  std::pair<Double_t, Double_t> centerJunk = trackJunk.GetGeoCenter();
205 
206  if (simulationConv) {
207 
208  thetaJunk = 180.0 - thetaJunk * TMath::RadToDeg();
209  } else {
210 
211  thetaJunk = thetaJunk * TMath::RadToDeg();
212  }
213 
214  if (thetaCand > 90) {
215 
216  /*if ((thetaCand + angleSpread) > thetaJunk && (thetaCand - angleSpread) < thetaJunk) {
217  for (auto hit : *hitArrayJunk) {
218 
219  track.AddHit(&hit);
220  ++jnkHitCnt;
221  }
222  }*/
223 
224  } else if (thetaCand < 90 && thetaJunk < 90) {
225 
226  if ((thetaCand + angleSpread) > thetaJunk && (thetaCand - angleSpread) < thetaJunk) { // Check angle
227  std::cout << " Center cand : " << centerCand.first << " - " << centerCand.second << " " << thetaCand
228  << "\n";
229  std::cout << " Center junk : " << centerJunk.first << " - " << centerJunk.second << " " << thetaJunk
230  << "\n";
231  Double_t centerDistance = TMath::Sqrt(TMath::Power(centerCand.first - centerJunk.first, 2) +
232  TMath::Power(centerCand.second - centerJunk.second, 2));
233  std::cout << " Distance " << centerDistance << "\n";
234  if (centerDistance < 50) // Check quadrant
235 
236  for (const auto &hit : hitArrayJunk) {
237 
238  track.AddHit(hit->Clone());
239  ++jnkHitCnt;
240  }
241  }
242  }
243 
244  ++jnkCnt;
245 
246  } // Junk track
247 
248  // track.SortClusterHitArrayZ();
249  track.SortHitArrayTime();
250 
251  // Prune if other tracks were added track
252 
253  if (trackJunkSource->size() > 0) {
254  Double_t pruneFraction = 10.0;
255  if (jnkHitCnt > hitArrayCand.size())
256  pruneFraction = 4.0; // 25%
257  else
258  pruneFraction = 10.0; // 10%
259 
260  Int_t numHits = (Int_t)track.GetHitArray().size() / pruneFraction;
261  for (auto iHit = 0; iHit < numHits; ++iHit)
262  track.GetHitArray().pop_back();
263  }
264 
265  trackDest->push_back(track);
266 
267  } // Source track
268 }
cYELLOW
constexpr auto cYELLOW
Definition: AtFitter.cxx:18
AtTrack::ResetHitClusterArray
void ResetHitClusterArray()
Definition: AtTrack.h:111
AtFITTER::AtFitter::GetMomFromBrho
std::tuple< Double_t, Double_t > GetMomFromBrho(Double_t A, Double_t Z, Double_t brho)
Returns momentum (in GeV) from Brho assuming M (amu) and Z;.
Definition: AtFitter.cxx:28
AtHitCluster.h
AtFITTER::AtFitter
Definition: AtFitter.h:26
AtFITTER::AtFitter::~AtFitter
virtual ~AtFitter()
cGREEN
constexpr auto cGREEN
Definition: AtFitter.cxx:20
AtTrack::SortHitArrayTime
void SortHitArrayTime()
Definition: AtTrack.cxx:119
AtFitter.h
AtFITTER::AtFitter::AtFitter
AtFitter()
AtFITTER::AtFitter::FindVertexTrack
Bool_t FindVertexTrack(AtTrack *trA, AtTrack *trB)
Lambda function to find track closer to vertex.
Definition: AtFitter.cxx:38
AtTrack::GetIsMerged
Bool_t GetIsMerged() const
Definition: AtTrack.h:92
AtHit.h
AtTrack::GetHitClusterArray
std::vector< AtHitCluster > * GetHitClusterArray()
Definition: AtTrack.h:90
AtTrack
Definition: AtTrack.h:25
AtTrack.h
cRED
constexpr auto cRED
Definition: AtFitter.cxx:17
AtTrack::GetTrackID
Int_t GetTrackID() const
Definition: AtTrack.h:78
AtTrack::SetIsMerged
void SetIsMerged(bool val)
Definition: AtTrack.h:107
AtTrack::GetGeoTheta
Double_t GetGeoTheta() const
Definition: AtTrack.h:86
cNORMAL
constexpr auto cNORMAL
Definition: AtFitter.cxx:19
AtFITTER::AtFitter::MergeTracks
void MergeTracks(std::vector< AtTrack > *trackCandSource, std::vector< AtTrack > *trackJunkSource, std::vector< AtTrack > *trackDest, bool fitDirection, bool simulationConv)
Definition: AtFitter.cxx:169
AtTrack::GetHitArray
HitVector & GetHitArray()
Definition: AtTrack.h:79
ClassImp
ClassImp(AtFITTER::AtFitter)
AtTrack::AddHit
void AddHit(const AtHit &hit)
Definition: AtTrack.h:97