REST-for-Physics  v2.3
Rare Event Searches ToolKit for Physics
TRestTrackReconnectionProcess.cxx
1 
12 #include "TRestTrackReconnectionProcess.h"
13 
14 using namespace std;
15 
17 
18 TRestTrackReconnectionProcess::TRestTrackReconnectionProcess() { Initialize(); }
19 
20 TRestTrackReconnectionProcess::TRestTrackReconnectionProcess(const char* configFilename) {
21  Initialize();
22 
23  if (LoadConfigFromFile(configFilename) == -1) LoadDefaultConfig();
24  PrintMetadata();
25 }
26 
27 TRestTrackReconnectionProcess::~TRestTrackReconnectionProcess() { delete fOutputTrackEvent; }
28 
29 void TRestTrackReconnectionProcess::LoadDefaultConfig() {
30  SetName("trackReconnectionProcess");
31  SetTitle("Default config");
32 }
33 
35  SetSectionName(this->ClassName());
36  SetLibraryVersion(LIBRARY_VERSION);
37 
38  fInputTrackEvent = nullptr;
39  fOutputTrackEvent = new TRestTrackEvent();
40 
41  fSplitTrack = false;
42 }
43 
44 void TRestTrackReconnectionProcess::LoadConfig(const string& configFilename, const string& name) {
45  if (LoadConfigFromFile(configFilename, name) == -1) LoadDefaultConfig();
46 
47  PrintMetadata();
48 }
49 
50 void TRestTrackReconnectionProcess::InitProcess() { TRestEventProcess::ReadObservables(); }
51 
53  Int_t trackBranches = 0;
54 
55  fInputTrackEvent = (TRestTrackEvent*)inputEvent;
56 
57  // Copying the input tracks to the output track
58  for (int tck = 0; tck < fInputTrackEvent->GetNumberOfTracks(); tck++)
59  fOutputTrackEvent->AddTrack(fInputTrackEvent->GetTrack(tck));
60 
61  for (int tck = 0; tck < fInputTrackEvent->GetNumberOfTracks(); tck++) {
62  if (!fInputTrackEvent->isTopLevel(tck)) continue;
63  Int_t tckId = fInputTrackEvent->GetTrack(tck)->GetTrackID();
64 
65  TRestVolumeHits* hits = fInputTrackEvent->GetTrack(tck)->GetVolumeHits();
66 
67  /* {{{ Debug output */
68  if (this->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) {
69  cout << "TRestTrackReconnectionProcess. Input hits" << endl;
70  Int_t pId = fInputTrackEvent->GetTrack(tck)->GetParentID();
71  cout << "Track : " << tck << " TrackID : " << tckId << " ParentID : " << pId << endl;
72  cout << "-----------------" << endl;
73  }
74  /* }}} */
75 
76  SetDistanceMeanAndSigma((TRestHits*)hits);
77 
78  if (fMeanDistance == 0) continue; // We have just 1-hit
79 
80  TRestVolumeHits initialHits = *hits;
81  vector<TRestVolumeHits> subHitSets;
82  Int_t tBranches;
83 
84  // We do 3 times the break and re-connect process
85  // Although another option would be to do it until we observe no change
86  // Most of the times even 1-round is more than enough.
87  for (int n = 0; n < 1; n++) {
88  // The required distance between hits to break a track is increased in
89  // each iteration
90  BreakTracks(&initialHits, subHitSets, 1.5 * (n + 1));
91  ReconnectTracks(subHitSets);
92 
93  TRestVolumeHits resultHits = subHitSets[0];
94  SetDistanceMeanAndSigma(&resultHits);
95  tBranches = GetTrackBranches(resultHits, fNSigmas);
96 
97  if (GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) {
98  cout << "Break and reconnect finished" << endl;
99  cout << "Branches : " << tBranches << endl;
101  }
102 
103  initialHits = resultHits;
104  }
105 
106  // For the observable We just take the value for the track with more number
107  // of branches
108  if (tBranches > trackBranches) trackBranches = tBranches;
109 
110  // A fine tunning applied to consecutive hits
111  for (unsigned int n = 0; n < subHitSets[0].GetNumberOfHits(); n++) {
112  if (n > 0 && n < subHitSets[0].GetNumberOfHits() - 1) {
113  Double_t distance = subHitSets[0].GetHitsPathLength(n - 2, n + 2);
114 
115  subHitSets[0].SwapHits(n - 1, n);
116 
117  Double_t distanceAfter = subHitSets[0].GetHitsPathLength(n - 2, n + 2);
118 
119  if (distanceAfter < distance) continue;
120 
121  subHitSets[0].SwapHits(n - 1, n);
122  }
123  }
124 
125  if (fSplitTrack) {
126  BreakTracks(&initialHits, subHitSets, fNSigmas);
127 
128  if (GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) {
129  cout << " **** Splitting track : " << endl;
130  cout << "Number of subHitSets : " << subHitSets.size() << endl;
132  }
133  }
134 
135  for (unsigned int n = 0; n < subHitSets.size(); n++) {
136  TRestTrack aTrack;
137  // We create the new track and add it giving its parent ID
138  aTrack.SetTrackID(fOutputTrackEvent->GetNumberOfTracks() + 1);
139 
140  aTrack.SetParentID(tckId);
141 
142  aTrack.SetVolumeHits(subHitSets[n]);
143 
144  fOutputTrackEvent->AddTrack(&aTrack);
145  }
146  }
147 
148  SetObservableValue("branches", trackBranches);
149  // cout << "Track branches : " << trackBranches << endl;
150 
151  if (GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) {
152  cout << "++++++++++++++++++++++++++++++++" << endl;
153  fOutputTrackEvent->PrintEvent();
154  cout << "++++++++++++++++++++++++++++++++" << endl;
156  }
157 
158  return fOutputTrackEvent;
159 }
160 
164 void TRestTrackReconnectionProcess::BreakTracks(TRestVolumeHits* hits, vector<TRestVolumeHits>& hitSets,
165  Double_t nSigma) {
166  hitSets.clear();
167  if (GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) {
168  cout << "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" << endl;
169  cout << "BreakTracks. Breaking tracks into hits subsets." << endl;
170  }
171 
172  TRestVolumeHits subHits;
173  for (unsigned int n = 0; n < hits->GetNumberOfHits(); n++) {
174  Double_t x = hits->GetX(n);
175  Double_t y = hits->GetY(n);
176  Double_t z = hits->GetZ(n);
177  Double_t sX = hits->GetSigmaX(n);
178  Double_t sY = hits->GetSigmaY(n);
179  Double_t sZ = hits->GetSigmaZ(n);
180  Double_t energy = hits->GetEnergy(n);
181 
182  if (GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug && n > 0) {
183  cout << "Distance : " << hits->GetDistance(n - 1, n);
184  if (hits->GetDistance(n - 1, n) > fMeanDistance + nSigma * fSigma) cout << " BREAKKKK";
185  cout << endl;
186  }
187 
188  if (n > 0 && hits->GetDistance(n - 1, n) > fMeanDistance + nSigma * fSigma) {
189  hitSets.push_back(subHits);
190  subHits.RemoveHits();
191  }
192 
193  subHits.AddHit(x, y, z, energy, 0, hits->GetType(n), sX, sY, sZ);
194 
195  if (GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug)
196  cout << "H : " << n << " X : " << x << " Y : " << y << " Z : " << z << endl;
197  }
198 
199  hitSets.push_back(subHits);
200 
201  if (GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug)
202  cout << "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" << endl;
203 }
204 
205 void TRestTrackReconnectionProcess::ReconnectTracks(vector<TRestVolumeHits>& hitSets) {
206  if (GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) {
207  cout << "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" << endl;
208  cout << "ReconnectTracks. Connecting back sub tracks " << endl;
209  }
210 
211  Int_t nSubTracks = hitSets.size();
212 
213  if (nSubTracks == 1) return;
214 
215  Double_t minDistance = 1.e10;
216 
217  Int_t tracks[2][2] = {{0, 0}, {0, 0}};
218 
219  vector<Int_t> nHits(nSubTracks);
220  for (int i = 0; i < nSubTracks; i++) nHits[i] = hitSets[i].GetNumberOfHits();
221 
222  if (GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) {
223  cout << "ORIGINAL" << endl;
224  cout << "--------" << endl;
225  for (int i = 0; i < nSubTracks; i++) {
226  cout << "Subset : " << i << endl;
227  cout << " Sub hits : " << nHits[i] << endl;
228 
229  hitSets[i].PrintHits();
230  }
231  cout << "--------" << endl;
232  }
233 
234  /* {{{ Finds the closest sub-track extremes */
235  for (int i = 0; i < nSubTracks; i++) {
236  for (int j = 0; j < nSubTracks; j++) {
237  if (i != j) {
238  Int_t x1_0 = hitSets[i].GetX(0);
239  Int_t x1_1 = hitSets[i].GetX(nHits[i] - 1);
240 
241  Int_t y1_0 = hitSets[i].GetY(0);
242  Int_t y1_1 = hitSets[i].GetY(nHits[i] - 1);
243 
244  Int_t z1_0 = hitSets[i].GetZ(0);
245  Int_t z1_1 = hitSets[i].GetZ(nHits[i] - 1);
246 
247  Int_t x2_0 = hitSets[j].GetX(0);
248  Int_t x2_1 = hitSets[j].GetX(nHits[j] - 1);
249 
250  Int_t y2_0 = hitSets[j].GetY(0);
251  Int_t y2_1 = hitSets[j].GetY(nHits[j] - 1);
252 
253  Int_t z2_0 = hitSets[j].GetZ(0);
254  Int_t z2_1 = hitSets[j].GetZ(nHits[j] - 1);
255 
256  Double_t d;
257  d = TMath::Sqrt((x1_0 - x2_0) * (x1_0 - x2_0) + (y1_0 - y2_0) * (y1_0 - y2_0) +
258  (z1_0 - z2_0) * (z1_0 - z2_0));
259 
260  if (d < minDistance) {
261  tracks[0][0] = i;
262  tracks[0][1] = 0;
263  tracks[1][0] = j;
264  tracks[1][1] = 0;
265  minDistance = d;
266  }
267 
268  d = TMath::Sqrt((x1_0 - x2_1) * (x1_0 - x2_1) + (y1_0 - y2_1) * (y1_0 - y2_1) +
269  (z1_0 - z2_1) * (z1_0 - z2_1));
270 
271  if (d < minDistance) {
272  tracks[0][0] = i;
273  tracks[0][1] = 0;
274  tracks[1][0] = j;
275  tracks[1][1] = 1;
276  minDistance = d;
277  }
278 
279  d = TMath::Sqrt((x1_1 - x2_0) * (x1_1 - x2_0) + (y1_1 - y2_0) * (y1_1 - y2_0) +
280  (z1_1 - z2_0) * (z1_1 - z2_0));
281 
282  if (d < minDistance) {
283  tracks[0][0] = i;
284  tracks[0][1] = 1;
285  tracks[1][0] = j;
286  tracks[1][1] = 0;
287  minDistance = d;
288  }
289 
290  d = TMath::Sqrt((x1_1 - x2_1) * (x1_1 - x2_1) + (y1_1 - y2_1) * (y1_1 - y2_1) +
291  (z1_1 - z2_1) * (z1_1 - z2_1));
292 
293  if (d < minDistance) {
294  tracks[0][0] = i;
295  tracks[0][1] = 1;
296  tracks[1][0] = j;
297  tracks[1][1] = 1;
298  minDistance = d;
299  }
300  }
301  }
302  }
303  /* }}} */
304 
305  /* {{{ Debug output
306  cout << "Tracks" << endl;
307  cout << tracks[0][0] << " ::: " << tracks[0][1] << endl;
308  cout << tracks[1][0] << " ::: " << tracks[1][1] << endl;
309  }}} */
310 
311  TRestVolumeHits newHits;
312  newHits.RemoveHits();
313 
314  Int_t tck1 = tracks[0][0];
315  Int_t tck2 = tracks[1][0];
316 
317  /* {{{ Rejoins the closest sub-track extremes into 1-single track */
318  if (tracks[0][1] == 0 && tracks[1][1] == 0) {
319  // We invert the first and add the second
320  for (int n = nHits[tck1] - 1; n >= 0; n--) newHits.AddHit(hitSets[tck1], n);
321 
322  for (int n = 0; n < nHits[tck2]; n++) newHits.AddHit(hitSets[tck2], n);
323  } else if (tracks[0][1] == 1 && tracks[1][1] == 0) {
324  // We add the first and then the second
325 
326  for (int n = 0; n < nHits[tck1]; n++) newHits.AddHit(hitSets[tck1], n);
327 
328  for (int n = 0; n < nHits[tck2]; n++) newHits.AddHit(hitSets[tck2], n);
329  } else if (tracks[0][1] == 0 && tracks[1][1] == 1) {
330  // We add the second and then the first
331 
332  for (int n = 0; n < nHits[tck2]; n++) newHits.AddHit(hitSets[tck2], n);
333 
334  for (int n = 0; n < nHits[tck1]; n++) newHits.AddHit(hitSets[tck1], n);
335  } else {
336  // We add the first and invert the second
337 
338  for (int n = 0; n < nHits[tck1]; n++) newHits.AddHit(hitSets[tck1], n);
339 
340  for (int n = nHits[tck2] - 1; n >= 0; n--) newHits.AddHit(hitSets[tck2], n);
341  }
342 
343  hitSets.erase(hitSets.begin() + tck2);
344  hitSets.erase(hitSets.begin() + tck1);
345  hitSets.push_back(newHits);
346  /* }}} */
347 
348  nSubTracks = hitSets.size();
349 
350  if (GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) {
351  cout << "New subtracks : " << nSubTracks << endl;
352 
353  cout << "AFTER REMOVAL" << endl;
354  cout << "--------" << endl;
355  for (int i = 0; i < nSubTracks; i++) {
356  cout << "Subset : " << i << endl;
357  cout << " Sub hits : " << nHits[i] << endl;
358 
359  hitSets[i].PrintHits();
360  }
361  cout << "--------" << endl;
363  }
364 
365  if (nSubTracks > 1) ReconnectTracks(hitSets);
366 
367  if (GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug)
368  cout << "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" << endl;
369 }
370 
371 Int_t TRestTrackReconnectionProcess::GetTrackBranches(TRestHits& h, Double_t nSigma) {
372  Int_t breaks = 0;
373  Int_t nHits = h.GetNumberOfHits();
374 
375  for (int n = 1; n < nHits; n++)
376  if (h.GetDistance(n - 1, n) > fMeanDistance + nSigma * fSigma) breaks++;
377  return breaks;
378 }
379 
381 
383  if (GetParameter("splitTrack", "false") == "true")
384  fSplitTrack = true;
385  else
386  fSplitTrack = false;
387 
388  fNSigmas = StringToDouble(GetParameter("nSigmas", "5"));
389 }
390 
391 void TRestTrackReconnectionProcess::SetDistanceMeanAndSigma(TRestHits* h) {
392  Int_t nHits = h->GetNumberOfHits();
393 
394  fMeanDistance = 0;
395  for (int n = 1; n < nHits; n++) fMeanDistance += h->GetDistance(n - 1, n);
396  fMeanDistance /= nHits;
397 
398  fSigma = TMath::Sqrt(fMeanDistance);
399 
400  if (GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) {
401  cout << "-----> Node distance average ; " << fMeanDistance << endl;
402  cout << "-----> Node distance sigma : " << fSigma << endl;
403  cout << endl;
404  }
405 }
A base class for any REST event.
Definition: TRestEvent.h:38
It saves a 3-coordinate position and an energy for each punctual deposition.
Definition: TRestHits.h:39
Double_t GetHitsPathLength(Int_t n=0, Int_t m=0) const
It determines the distance required to travel from hit n to hit m adding all the distances of the hit...
Definition: TRestHits.cxx:1179
@ REST_Debug
+show the defined debug messages
void EndProcess() override
To be executed at the end of the run (outside event loop)
void InitProcess() override
To be executed at the beginning of the run (outside event loop)
TRestEvent * ProcessEvent(TRestEvent *inputEvent) override
Process one event.
void BreakTracks(TRestVolumeHits *hits, std::vector< TRestVolumeHits > &hitSets, Double_t nSigma=2.)
void InitFromConfigFile() override
To make settings from rml file. This method must be implemented in the derived class.
void Initialize() override
Making default settings.
void RemoveHits()
It removes all hits inside the class.
Int_t GetChar(std::string hint="Press a KEY to continue ...")
Helps to pause the program, printing a message before pausing.
Double_t StringToDouble(std::string in)
Gets a double from a string.