All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SeedFinderAlgorithm.cxx
Go to the documentation of this file.
1 //
2 // Name: SeedFinderAlgorithm.cxx
3 //
4 // Purpose: Implementation file for module SeedFinderAlgorithm.
5 //
6 // Ben Jones, MIT
7 //
8 
9 #include <stdint.h>
10 
11 #include "art/Framework/Principal/Event.h"
12 #include "art/Framework/Services/Registry/ServiceHandle.h"
13 #include "canvas/Utilities/Exception.h"
14 #include "messagefacility/MessageLogger/MessageLogger.h"
15 
24 
25 namespace trkf {
26 
27  //----------------------------------------------------------------------------
28  SeedFinderAlgorithm::SeedFinderAlgorithm(const fhicl::ParameterSet& pset) { reconfigure(pset); }
29 
30  //----------------------------------------------------------------------------
31  void
32  SeedFinderAlgorithm::reconfigure(fhicl::ParameterSet const& pset)
33  {
34 
35  fSptalg = new trkf::SpacePointAlg(pset.get<fhicl::ParameterSet>("SpacePointAlg"));
36 
37  fInitSeedLength = pset.get<double>("InitSeedLength");
38  fMinPointsInSeed = pset.get<int>("MinPointsInSeed");
39 
40  fRefits = pset.get<double>("Refits");
41 
42  fHitResolution = pset.get<double>("HitResolution");
43 
44  fOccupancyCut = pset.get<double>("OccupancyCut");
45  fLengthCut = pset.get<double>("LengthCut");
46  fExtendSeeds = pset.get<bool>("ExtendSeeds");
47 
48  fAllow2DSeeds = pset.get<bool>("Allow2DSeeds", false);
49 
50  fMaxViewRMS.resize(3);
51  fMaxViewRMS = pset.get<std::vector<double>>("MaxViewRMS");
52 
54  }
55 
56  //------------------------------------------------------------
57  // Given a set of spacepoints, find seeds, and catalogue
58  // spacepoints by the seeds they formed
59  //
60  std::vector<recob::Seed>
63  art::PtrVector<recob::Hit> const& HitsFlat,
64  std::vector<art::PtrVector<recob::Hit>>& CataloguedHits,
65  unsigned int StopAfter) const
66  {
67  // Vector of seeds found to return
68  std::vector<recob::Seed> ReturnVector;
69 
70  // First check if there is any overlap
71  std::vector<recob::SpacePoint> spts;
72 
74  fSptalg->makeSpacePoints(clockData, detProp, HitsFlat, spts);
75 
76  if (int(spts.size()) < fMinPointsInSeed) { return std::vector<recob::Seed>(); }
77 
78  // If we got here, we have enough spacepoints to potentially make seeds from these hits.
79 
80  // This is table will let us quickly look up which hits are in a given view / channel.
81  // structure is OrgHits[View][Channel] = {index1,index2...}
82  // where the indices are of HitsFlat[index].
83 
84  std::vector<std::vector<std::vector<int>>> OrgHits(3);
85  for (size_t n = 0; n != 3; ++n)
86  OrgHits[n].resize(fNChannels);
87 
88  // These two tables contain the hit to spacepoint mappings
89 
90  std::vector<std::vector<int>> SpacePointsPerHit(HitsFlat.size(), std::vector<int>());
91  std::vector<std::vector<int>> HitsPerSpacePoint(spts.size(), std::vector<int>());
92 
93  // This vector records the status of each hit.
94  // The possible values are:
95  // 0. hit unused
96  // 1. hit used in a seed
97  // Initially none are used.
98 
99  std::vector<char> HitStatus(HitsFlat.size(), 0);
100 
101  // Fill the organizing map
102 
103  for (size_t i = 0; i != HitsFlat.size(); ++i) {
104  OrgHits[HitsFlat.at(i)->View()][HitsFlat.at(i)->Channel()].push_back(i);
105  }
106 
107  // Fill the spacepoint / hit lookups
108 
109  for (size_t iSP = 0; iSP != spts.size(); ++iSP) {
110  art::PtrVector<recob::Hit> HitsThisSP = fSptalg->getAssociatedHits(spts.at(iSP));
111 
112  for (size_t iH = 0; iH != HitsThisSP.size(); ++iH) {
113  geo::View_t ThisView = HitsThisSP.at(iH)->View();
114  uint32_t ThisChannel = HitsThisSP.at(iH)->Channel();
115  float ThisTime = HitsThisSP.at(iH)->PeakTime();
116  float eta = 0.001;
117 
118  for (size_t iOrg = 0; iOrg != OrgHits[ThisView][ThisChannel].size(); ++iOrg) {
119  if (fabs(ThisTime - HitsFlat.at(OrgHits[ThisView][ThisChannel][iOrg])->PeakTime()) <
120  eta) {
121  SpacePointsPerHit.at(OrgHits[ThisView][ThisChannel][iOrg]).push_back(iSP);
122  HitsPerSpacePoint.at(iSP).push_back(OrgHits[ThisView][ThisChannel][iOrg]);
123  }
124  }
125  }
126  }
127 
128  // The general idea will be:
129  // A. Make spacepoints from remaining hits
130  // B. Look for 1 seed in that vector
131  // C. Discard used hits
132  // D. Repeat
133 
134  // This vector keeps track of the status of each space point.
135  // The key is the position in the AllSpacePoints vector.
136  // The value is
137  // 0: point unused
138  // 1: point used in seed
139  // 2: point thrown but unused
140  // 3: flag to terminate seed finding
141 
142  std::vector<char> PointStatus(spts.size(), 0);
143 
144  std::vector<std::map<geo::View_t, std::vector<int>>> WhichHitsPerSeed;
145 
146  bool KeepChopping = true;
147 
148  while (KeepChopping) {
149  // This vector keeps a list of the points used in this seed
150  std::vector<int> PointsUsed;
151 
152  // Find exactly one seed, starting at high Z
153  recob::Seed TheSeed =
154  FindSeedAtEnd(detProp, spts, PointStatus, PointsUsed, HitsFlat, OrgHits);
155 
156  // If it was a good seed, collect up the relevant spacepoints
157  // and add the seed to the return vector
158 
159  if (TheSeed.IsValid()) {
160 
161  for (size_t iP = 0; iP != PointsUsed.size(); ++iP) {
162  for (size_t iH = 0; iH != HitsPerSpacePoint.at(PointsUsed.at(iP)).size(); ++iH) {
163  int UsedHitID = HitsPerSpacePoint.at(PointsUsed.at(iP)).at(iH);
164  HitStatus[UsedHitID] = 2;
165  }
166  }
167  PointStatus[PointsUsed.at(0)] = 1;
168  ConsolidateSeed(detProp, TheSeed, HitsFlat, HitStatus, OrgHits, false);
169  }
170 
171  if (TheSeed.IsValid()) {
172  if (fRefits > 0) {
173  std::vector<char> HitStatusGood;
174  recob::Seed SeedGood;
175  for (size_t r = 0; r != (unsigned int)fRefits; ++r) {
176  double PrevLength = TheSeed.GetLength();
177 
178  SeedGood = TheSeed;
179  HitStatusGood = HitStatus;
180 
181  std::vector<int> PresentHitList;
182  for (size_t iH = 0; iH != HitStatus.size(); ++iH) {
183  if (HitStatus[iH] == 2) { PresentHitList.push_back(iH); }
184  }
185  double pt[3], dir[3], err[3];
186 
187  TheSeed.GetPoint(pt, err);
188  TheSeed.GetDirection(dir, err);
189 
190  TVector3 Center, Direction;
191  std::vector<double> ViewRMS;
192  std::vector<int> HitsPerView;
194  detProp, HitsFlat, PresentHitList, Center, Direction, ViewRMS, HitsPerView);
195 
196  Direction = Direction.Unit() * TheSeed.GetLength();
197 
198  int nViewsWithHits(0);
199  for (size_t n = 0; n != 3; ++n) {
200  pt[n] = Center[n];
201  dir[n] = Direction[n];
202 
203  TheSeed.SetPoint(pt, err);
204  TheSeed.SetDirection(dir, err);
205 
206  if (HitsPerView[n] > 0) nViewsWithHits++;
207  }
208 
209  if (nViewsWithHits < 2) TheSeed.SetValidity(false);
210 
211  if (TheSeed.IsValid())
212  ConsolidateSeed(detProp, TheSeed, HitsFlat, HitStatus, OrgHits, fExtendSeeds);
213 
214  // if we accidentally invalidated the seed, go back to the old one and escape
215  else {
216  // If we invalidated the seed, go back one interaction
217  // and kill the loop
218  HitStatus = HitStatusGood;
219  TheSeed = SeedGood;
220  break;
221  }
222  if ((r > 0) && (fabs(PrevLength - TheSeed.GetLength()) < fPitches.at(0))) {
223  // If we didn't change much, kill the loop
224  break;
225  }
226  }
227  }
228  }
229 
230  if (TheSeed.IsValid()) {
231  WhichHitsPerSeed.push_back(std::map<geo::View_t, std::vector<int>>());
232 
233  art::PtrVector<recob::Hit> HitsWithThisSeed;
234  for (size_t iH = 0; iH != HitStatus.size(); ++iH) {
235  if (HitStatus.at(iH) == 2) {
236  WhichHitsPerSeed.at(WhichHitsPerSeed.size() - 1)[HitsFlat[iH]->View()].push_back(iH);
237  HitsWithThisSeed.push_back(HitsFlat.at(iH));
238  HitStatus.at(iH) = 1;
239 
240  for (size_t iSP = 0; iSP != SpacePointsPerHit.at(iH).size(); ++iSP) {
241  PointStatus[SpacePointsPerHit.at(iH).at(iSP)] = 1;
242  }
243  }
244  }
245 
246  // Record that we used this set of hits with this seed in the return catalogue
247  ReturnVector.push_back(TheSeed);
248  CataloguedHits.push_back(HitsWithThisSeed);
249 
250  // Tidy up
251  HitsWithThisSeed.clear();
252  }
253  else {
254  // If it was not a good seed, throw out the top SP and try again
255  PointStatus.at(PointsUsed.at(0)) = 2;
256  }
257 
258  int TotalSPsUsed = 0;
259  for (size_t i = 0; i != PointStatus.size(); ++i) {
260  if (PointStatus[i] != 0) TotalSPsUsed++;
261  }
262 
263  if ((int(spts.size()) - TotalSPsUsed) < fMinPointsInSeed) KeepChopping = false;
264 
265  if ((PointStatus[0] == 3) || (PointStatus.size() == 0)) KeepChopping = false;
266 
267  PointsUsed.clear();
268 
269  if ((ReturnVector.size() >= StopAfter) && (StopAfter > 0)) break;
270 
271  } // end spt-level loop
272 
273  // If we didn't find any seeds, we can make one last ditch attempt. See
274  // if the whole collection is colinear enough to make one megaseed
275  // (good for patching up high angle tracks)
276 
277  if (ReturnVector.size() == 0) {
278  std::vector<int> ListAllHits;
279  for (size_t i = 0; i != HitsFlat.size(); ++i) {
280  ListAllHits.push_back(i);
281  HitStatus[i] = 2;
282  }
283  TVector3 SeedCenter(0, 0, 0);
284  TVector3 SeedDirection(0, 0, 0);
285 
286  std::vector<double> ViewRMS;
287  std::vector<int> HitsPerView;
288 
289  std::vector<art::PtrVector<recob::Hit>> HitsInThisCollection(3);
290 
292  detProp, HitsFlat, ListAllHits, SeedCenter, SeedDirection, ViewRMS, HitsPerView);
293 
294  bool ThrowOutSeed = false;
295 
296  double PtArray[3], DirArray[3];
297  int nViewsWithHits(0);
298  for (size_t n = 0; n != 3; ++n) {
299  PtArray[n] = SeedCenter[n];
300  DirArray[n] = SeedDirection[n];
301  if (HitsPerView[n] > 0) nViewsWithHits++;
302  }
303  recob::Seed TheSeed(PtArray, DirArray);
304 
305  if (nViewsWithHits < 2 || (nViewsWithHits < 3 && !fAllow2DSeeds)) ThrowOutSeed = true;
306 
307  if (!ThrowOutSeed) {
308  ConsolidateSeed(detProp, TheSeed, HitsFlat, HitStatus, OrgHits, false);
309 
310  // Now we have consolidated, grab the right
311  // hits to find the RMS and refitted direction
312  ListAllHits.clear();
313  for (size_t i = 0; i != HitStatus.size(); ++i) {
314  if (HitStatus.at(i) == 2) ListAllHits.push_back(i);
315  }
316  std::vector<int> HitsPerView;
318  detProp, HitsFlat, ListAllHits, SeedCenter, SeedDirection, ViewRMS, HitsPerView);
319 
320  int nViewsWithHits(0);
321  for (size_t n = 0; n != 3; ++n) {
322  PtArray[n] = SeedCenter[n];
323  DirArray[n] = SeedDirection[n];
324  // ThrowOutSeed = true;
325  if (HitsPerView[n] > 0) nViewsWithHits++;
326  }
327 
328  if (nViewsWithHits < 2 || (nViewsWithHits < 3 && !fAllow2DSeeds)) ThrowOutSeed = true;
329 
330  TheSeed = recob::Seed(PtArray, DirArray);
331 
332  if (fMaxViewRMS.at(0) > 0) {
333  for (size_t j = 0; j != fMaxViewRMS.size(); j++) {
334  if (fMaxViewRMS.at(j) < ViewRMS.at(j)) { ThrowOutSeed = true; }
335  }
336  }
337  }
338 
339  if ((!ThrowOutSeed) && (TheSeed.IsValid())) {
340  ReturnVector.push_back(TheSeed);
341  art::PtrVector<recob::Hit> HitsThisSeed;
342  for (size_t i = 0; i != ListAllHits.size(); ++i) {
343  HitsThisSeed.push_back(HitsFlat.at(ListAllHits.at(i)));
344  }
345  CataloguedHits.push_back(HitsThisSeed);
346  }
347  }
348 
349  // Tidy up
350  SpacePointsPerHit.clear();
351  HitsPerSpacePoint.clear();
352  PointStatus.clear();
353  OrgHits.clear();
354  HitStatus.clear();
355 
356  for (size_t i = 0; i != ReturnVector.size(); ++i) {
357  double CrazyValue = 1000000;
358  double Length = ReturnVector.at(i).GetLength();
359  if (!((Length > fLengthCut) && (Length < CrazyValue))) {
360  ReturnVector.erase(ReturnVector.begin() + i);
361  CataloguedHits.erase(CataloguedHits.begin() + i);
362  --i;
363  }
364  }
365 
366  return ReturnVector;
367  }
368 
369  //------------------------------------------------------------
370  // Latest extendseed method
371  //
372 
373  void
375  recob::Seed& TheSeed,
376  art::PtrVector<recob::Hit> const& HitsFlat,
377  std::vector<char>& HitStatus,
378  std::vector<std::vector<std::vector<int>>>& OrgHits,
379  bool Extend) const
380  {
381 
382  bool ThrowOutSeed = false;
383 
384  // This will keep track of what hits are in this seed
385  std::map<geo::View_t, std::map<uint32_t, std::vector<int>>> HitsInThisSeed;
386 
387  int NHitsThisSeed = 0;
388 
389  double MinS = 1000, MaxS = -1000;
390  for (size_t i = 0; i != HitStatus.size(); ++i) {
391  if (HitStatus.at(i) == 2) {
392  double disp, s;
393  GetHitDistAndProj(detProp, TheSeed, HitsFlat.at(i), disp, s);
394  if (fabs(s) > 1.2) {
395  // This hit is not rightfully part of this seed, toss it.
396  HitStatus[i] = 0;
397  }
398  else {
399  NHitsThisSeed++;
400 
401  if (s < MinS) MinS = s;
402  if (s > MaxS) MaxS = s;
403  HitsInThisSeed[HitsFlat.at(i)->View()][HitsFlat.at(i)->Channel()].push_back(i);
404  }
405  }
406  }
407 
408  double LengthRescale = (MaxS - MinS) / 2.;
409  double PositionShift = (MaxS + MinS) / 2.;
410 
411  double pt[3], dir[3], err[3];
412  TheSeed.GetPoint(pt, err);
413  TheSeed.GetDirection(dir, err);
414 
415  for (size_t n = 0; n != 3; ++n) {
416  pt[n] += dir[n] * PositionShift;
417  dir[n] *= LengthRescale;
418  }
419 
420  TheSeed.SetPoint(pt, err);
421  TheSeed.SetDirection(dir, err);
422 
423  // Run through checking if we missed any hits
424  for (auto itP = HitsInThisSeed.begin(); itP != HitsInThisSeed.end(); ++itP) {
425  double dist, s;
426  geo::View_t View = itP->first;
427  uint32_t LowestChan = itP->second.begin()->first;
428  uint32_t HighestChan = itP->second.rbegin()->first;
429  for (uint32_t c = LowestChan; c != HighestChan; ++c) {
430  for (size_t h = 0; h != OrgHits[View][c].size(); ++h) {
431  if (HitStatus[OrgHits[View][c].at(h)] == 0) {
432  GetHitDistAndProj(detProp, TheSeed, HitsFlat[OrgHits[View][c].at(h)], dist, s);
433  if (dist < fHitResolution) {
434  NHitsThisSeed++;
435 
436  HitStatus[OrgHits[View][c].at(h)] = 2;
437 
438  HitsInThisSeed[View][c].push_back(OrgHits[View][c].at(h));
439  }
440  else
441  HitStatus[OrgHits[View][c].at(h)] = 0;
442  }
443  }
444  }
445  }
446 
447  if (NHitsThisSeed == 0) ThrowOutSeed = true;
448 
449  // Check seed occupancy
450 
451  uint32_t LowestChanInSeed[3], HighestChanInSeed[3];
452  double Occupancy[] = {0., 0., 0.};
453  int nHitsPerView[] = {0, 0, 0};
454 
455  for (auto itP = HitsInThisSeed.begin(); itP != HitsInThisSeed.end(); ++itP) {
456 
457  geo::View_t View = itP->first;
458 
459  LowestChanInSeed[View] = itP->second.begin()->first;
460  HighestChanInSeed[View] = itP->second.rbegin()->first;
461 
462  nHitsPerView[View]++;
463 
464  int FilledChanCount = 0;
465 
466  for (size_t c = LowestChanInSeed[View]; c != HighestChanInSeed[View]; ++c) {
467  if (itP->second[c].size() > 0) ++FilledChanCount;
468  }
469 
470  Occupancy[View] =
471  float(FilledChanCount) / float(HighestChanInSeed[View] - LowestChanInSeed[View]);
472  }
473 
474  int nBelowCut(0);
475  int nViewsWithHits(0);
476  for (size_t n = 0; n != 3; ++n) {
477  if (Occupancy[n] < fOccupancyCut) nBelowCut++;
478  if (nHitsPerView[n] > 0) nViewsWithHits++;
479  }
480 
481  int belowCut(0);
482 
483  if (fAllow2DSeeds && nViewsWithHits < 3) belowCut = 1;
484 
485  if (nBelowCut > belowCut) ThrowOutSeed = true;
486 
487  if ((Extend) && (!ThrowOutSeed)) {
488  std::vector<std::vector<double>> ToAddNegativeS(3, std::vector<double>());
489  std::vector<std::vector<double>> ToAddPositiveS(3, std::vector<double>());
490  std::vector<std::vector<int>> ToAddNegativeH(3, std::vector<int>());
491  std::vector<std::vector<int>> ToAddPositiveH(3, std::vector<int>());
492 
493  for (auto itP = HitsInThisSeed.begin(); itP != HitsInThisSeed.end(); ++itP) {
494  double dist, s;
495 
496  geo::View_t View = itP->first;
497 
498  if (LowestChanInSeed[View] > 0) {
499  for (uint32_t c = LowestChanInSeed[View] - 1; c != 0; --c) {
500  bool GotOneThisChannel = false;
501  for (size_t h = 0; h != OrgHits[View][c].size(); ++h) {
502  if (HitStatus[OrgHits[View][c][h]] == 0) {
503  GetHitDistAndProj(detProp, TheSeed, HitsFlat[OrgHits[View][c].at(h)], dist, s);
504  if (dist < fHitResolution) {
505  GotOneThisChannel = true;
506  if (s < 0) {
507  ToAddNegativeS[View].push_back(s);
508  ToAddNegativeH[View].push_back(OrgHits[View][c].at(h));
509  }
510  else {
511  ToAddPositiveS[View].push_back(s);
512  ToAddPositiveH[View].push_back(OrgHits[View][c].at(h));
513  }
514  }
515  }
516  }
517  if (GotOneThisChannel == false) break;
518  }
519  }
520  if (HighestChanInSeed[View] < fNChannels)
521 
522  for (uint32_t c = HighestChanInSeed[View] + 1; c != fNChannels; ++c) {
523  bool GotOneThisChannel = false;
524  for (size_t h = 0; h != OrgHits[View][c].size(); ++h) {
525  if (HitStatus[OrgHits[View][c][h]] == 0) {
526  GetHitDistAndProj(detProp, TheSeed, HitsFlat[OrgHits[View][c].at(h)], dist, s);
527  if (dist < fHitResolution) {
528  GotOneThisChannel = true;
529  if (s < 0) {
530 
531  ToAddNegativeS[View].push_back(s);
532  ToAddNegativeH[View].push_back(OrgHits[View][c].at(h));
533  }
534  else {
535  ToAddPositiveS[View].push_back(s);
536  ToAddPositiveH[View].push_back(OrgHits[View][c].at(h));
537  }
538  }
539  }
540  }
541  if (GotOneThisChannel == false) break;
542  }
543  }
544 
545  double ExtendPositiveS = 0, ExtendNegativeS = 0;
546 
547  if ((ToAddPositiveS[0].size() > 0) && (ToAddPositiveS[1].size() > 0) &&
548  (ToAddPositiveS[2].size() > 0)) {
549  for (size_t n = 0; n != 3; ++n) {
550  int n1 = (n + 1) % 3;
551  int n2 = (n + 2) % 3;
552 
553  if ((ToAddPositiveS[n].back() <= ToAddPositiveS[n1].back()) &&
554  (ToAddPositiveS[n].back() <= ToAddPositiveS[n2].back())) {
555  ExtendPositiveS = ToAddPositiveS[n].back();
556  }
557  }
558  }
559 
560  if ((ToAddNegativeS[0].size() > 0) && (ToAddNegativeS[1].size() > 0) &&
561  (ToAddNegativeS[2].size() > 0)) {
562  for (size_t n = 0; n != 3; ++n) {
563  int n1 = (n + 1) % 3;
564  int n2 = (n + 2) % 3;
565  if ((ToAddNegativeS[n].back() >= ToAddNegativeS[n1].back()) &&
566  (ToAddNegativeS[n].back() >= ToAddNegativeS[n2].back())) {
567  ExtendNegativeS = ToAddNegativeS[n].back();
568  }
569  }
570  }
571 
572  if (fabs(ExtendNegativeS) < 1.) ExtendNegativeS = -1.;
573  if (fabs(ExtendPositiveS) < 1.) ExtendPositiveS = 1.;
574 
575  LengthRescale = (ExtendPositiveS - ExtendNegativeS) / 2.;
576  PositionShift = (ExtendPositiveS + ExtendNegativeS) / 2.;
577 
578  for (size_t n = 0; n != 3; ++n) {
579  pt[n] += dir[n] * PositionShift;
580  dir[n] *= LengthRescale;
581 
582  for (size_t i = 0; i != ToAddPositiveS[n].size(); ++i) {
583  if (ToAddPositiveS[n].at(i) < ExtendPositiveS)
584  HitStatus[ToAddPositiveH[n].at(i)] = 2;
585  else
586  HitStatus[ToAddPositiveH[n].at(i)] = 0;
587  }
588 
589  for (size_t i = 0; i != ToAddNegativeS[n].size(); ++i) {
590  if (ToAddNegativeS[n].at(i) > ExtendNegativeS)
591  HitStatus[ToAddNegativeH[n].at(i)] = 2;
592  else
593  HitStatus[ToAddNegativeH[n].at(i)] = 0;
594  }
595  }
596 
597  TheSeed.SetPoint(pt, err);
598  TheSeed.SetDirection(dir, err);
599  }
600 
601  if (ThrowOutSeed) TheSeed.SetValidity(false);
602  }
603 
604  //------------------------------------------------------------
605 
606  void
608  recob::Seed const& ASeed,
609  art::Ptr<recob::Hit> const& AHit,
610  double& disp,
611  double& s) const
612  {
613  art::ServiceHandle<geo::Geometry const> geom;
614 
615  double xyzStart[3], xyzEnd[3];
616 
617  geom->WireEndPoints(0, 0, AHit->WireID().Plane, AHit->WireID().Wire, xyzStart, xyzEnd);
618 
619  double HitX = detProp.ConvertTicksToX(AHit->PeakTime(), AHit->WireID().Plane, 0, 0);
620 
621  double HitXHigh = detProp.ConvertTicksToX(AHit->PeakTimePlusRMS(), AHit->WireID().Plane, 0, 0);
622  double HitXLow = detProp.ConvertTicksToX(AHit->PeakTimeMinusRMS(), AHit->WireID().Plane, 0, 0);
623 
624  double HitWidth = HitXHigh - HitXLow;
625 
626  double pt[3], dir[3], err[3];
627 
628  ASeed.GetDirection(dir, err);
629  ASeed.GetPoint(pt, err);
630 
631  TVector3 sPt(pt[0], pt[1], pt[2]);
632  TVector3 sDir(dir[0], dir[1], dir[2]);
633  TVector3 hPt(HitX, xyzStart[1], xyzStart[2]);
634  TVector3 hDir(0, xyzStart[1] - xyzEnd[1], xyzStart[2] - xyzEnd[2]);
635 
636  s = (sPt - hPt).Dot(hDir * (hDir.Dot(sDir)) - sDir * (hDir.Dot(hDir))) /
637  (hDir.Dot(hDir) * sDir.Dot(sDir) - pow(hDir.Dot(sDir), 2));
638 
639  disp = fabs((sPt - hPt).Dot(sDir.Cross(hDir)) / (sDir.Cross(hDir)).Mag()) / HitWidth;
640  }
641 
642  //------------------------------------------------------------
643  // Try to find one seed at the high Z end of a set of spacepoints
644  //
645 
648  std::vector<recob::SpacePoint> const& Points,
649  std::vector<char>& PointStatus,
650  std::vector<int>& PointsInRange,
651  art::PtrVector<recob::Hit> const& HitsFlat,
652  std::vector<std::vector<std::vector<int>>>& OrgHits) const
653  {
654  // This pointer will be returned later
655  recob::Seed ReturnSeed;
656 
657  // Keep track of spacepoints we used, not just their IDs
658  std::vector<recob::SpacePoint> PointsUsed;
659 
660  // Clear output vector
661  PointsInRange.clear();
662 
663  // Loop through hits looking for highest Z seedable point
664  TVector3 HighestZPoint;
665  bool NoPointFound = true;
666  int counter = Points.size() - 1;
667  while ((NoPointFound == true) && (counter >= 0)) {
668  if (PointStatus[counter] == 0) {
669  HighestZPoint = TVector3(
670  Points.at(counter).XYZ()[0], Points.at(counter).XYZ()[1], Points.at(counter).XYZ()[2]);
671  NoPointFound = false;
672  }
673  else
674  counter--;
675  }
676  if (NoPointFound) {
677  // We didn't find a high point at all
678  // - let the algorithm know to give up.
679  PointStatus[0] = 3;
680  }
681 
682  // Now we have the high Z point, loop through collecting
683  // near enough hits. We look 2 seed lengths away, since
684  // the seed is bidirectional from the central point
685 
686  double TwiceLength = 2.0 * fInitSeedLength;
687 
688  for (int index = Points.size() - 1; index != -1; --index) {
689  if (PointStatus[index] == 0) {
690  // first check z, then check total distance
691  // (much faster, since most will be out of range in z anyway)
692  if ((HighestZPoint[2] - Points.at(index).XYZ()[2]) < TwiceLength) {
693  double DistanceToHighZ = pow(pow(HighestZPoint[1] - Points.at(index).XYZ()[1], 2) +
694  pow(HighestZPoint[2] - Points.at(index).XYZ()[2], 2),
695  0.5);
696  if (DistanceToHighZ < TwiceLength) {
697  PointsInRange.push_back(index);
698  PointsUsed.push_back(Points.at(index));
699  }
700  }
701  else
702  break;
703  }
704  }
705 
706  TVector3 SeedCenter(0, 0, 0);
707  TVector3 SeedDirection(0, 0, 0);
708 
709  // Check we have enough points in here to form a seed,
710  // otherwise return a dud
711  int NPoints = PointsInRange.size();
712 
713  if (NPoints < fMinPointsInSeed) return recob::Seed();
714 
715  std::map<int, bool> HitMap;
716  std::vector<int> HitList;
717 
718  for (unsigned int i = 0; i != PointsInRange.size(); i++) {
719  std::vector<art::PtrVector<recob::Hit>> HitsInThisCollection(3);
720 
721  art::PtrVector<recob::Hit> HitsThisSP =
722  fSptalg->getAssociatedHits((Points.at(PointsInRange.at(i))));
723  for (art::PtrVector<recob::Hit>::const_iterator itHit = HitsThisSP.begin();
724  itHit != HitsThisSP.end();
725  ++itHit) {
726  uint32_t Channel = (*itHit)->Channel();
727  geo::View_t View = (*itHit)->View();
728 
729  double eta = 0.01;
730  for (size_t iH = 0; iH != OrgHits[View][Channel].size(); ++iH) {
731  if (fabs(HitsFlat[OrgHits[View][Channel][iH]]->PeakTime() - (*itHit)->PeakTime()) < eta) {
732  HitMap[OrgHits[View][Channel][iH]] = true;
733  }
734  }
735  }
736  }
737 
738  for (auto itH = HitMap.begin(); itH != HitMap.end(); ++itH) {
739  HitList.push_back(itH->first);
740  }
741 
742  std::vector<double> ViewRMS;
743  std::vector<int> HitsPerView;
744 
746  detProp, HitsFlat, HitList, SeedCenter, SeedDirection, ViewRMS, HitsPerView);
747 
748  HitMap.clear();
749  HitList.clear();
750 
751  // See if seed points have some linearity
752 
753  bool ThrowOutSeed = false;
754 
755  double PtArray[3], DirArray[3];
756  double AngleFactor =
757  pow(pow(SeedDirection.Y(), 2) + pow(SeedDirection.Z(), 2), 0.5) / SeedDirection.Mag();
758 
759  int nViewsWithHits(0);
760 
761  for (size_t n = 0; n != 3; ++n) {
762  DirArray[n] = SeedDirection[n] * fInitSeedLength / AngleFactor;
763  PtArray[n] = SeedCenter[n];
764  if (HitsPerView[n] > 0) nViewsWithHits++;
765  }
766 
767  if (nViewsWithHits < 2 || (nViewsWithHits < 3 && !fAllow2DSeeds)) ThrowOutSeed = true;
768 
769  ReturnSeed = recob::Seed(PtArray, DirArray);
770 
771  if (fMaxViewRMS.at(0) > 0) {
772 
773  for (size_t j = 0; j != fMaxViewRMS.size(); j++) {
774  if (fMaxViewRMS.at(j) < ViewRMS.at(j)) { ThrowOutSeed = true; }
775  // mf::LogVerbatim("SeedFinderAlgorithm") << RMS.at(j);
776  }
777  }
778 
779  // If the seed is marked as bad, return a dud, otherwise
780  // return the ReturnSeed pointer
781  if (!ThrowOutSeed)
782  return ReturnSeed;
783  else
784  return recob::Seed();
785  }
786 
787  //-----------------------------------------------------------
788 
789  void
791  art::PtrVector<recob::Hit> const& HitsFlat,
792  std::vector<int>& HitsToUse,
793  TVector3& Center,
794  TVector3& Direction,
795  std::vector<double>& ViewRMS,
796  std::vector<int>& N) const
797  {
798  N.resize(3);
799 
800  std::map<uint32_t, bool> HitsClaimed;
801 
802  // We'll store hit coordinates in each view into this vector
803 
804  std::vector<std::vector<double>> HitTimes(3);
805  std::vector<std::vector<double>> HitWires(3);
806  std::vector<std::vector<double>> HitWidths(3);
807  std::vector<double> MeanWireCoord(3, 0);
808  std::vector<double> MeanTimeCoord(3, 0);
809 
810  // Run through the collection getting hit info for these spacepoints
811 
812  std::vector<double> x(3, 0), y(3, 0), xx(3, 0), xy(3, 0), yy(3, 0), sig(3, 0);
813 
814  for (size_t i = 0; i != HitsToUse.size(); ++i) {
815  auto itHit = HitsFlat.begin() + HitsToUse[i];
816 
817  size_t ViewIndex;
818 
819  auto const hitView = (*itHit)->View();
820  if (hitView == geo::kU)
821  ViewIndex = 0;
822  else if (hitView == geo::kV)
823  ViewIndex = 1;
824  else if (hitView == geo::kW)
825  ViewIndex = 2;
826  else {
827  throw art::Exception(art::errors::LogicError)
828  << "SpacePointAlg does not support view " << geo::PlaneGeo::ViewName(hitView) << " (#"
829  << hitView << ")\n";
830  }
831  double WireCoord = (*itHit)->WireID().Wire * fPitches.at(ViewIndex);
832  double TimeCoord = detProp.ConvertTicksToX((*itHit)->PeakTime(), ViewIndex, 0, 0);
833  double TimeUpper = detProp.ConvertTicksToX((*itHit)->PeakTimePlusRMS(), ViewIndex, 0, 0);
834  double TimeLower = detProp.ConvertTicksToX((*itHit)->PeakTimeMinusRMS(), ViewIndex, 0, 0);
835  double Width = fabs(0.5 * (TimeUpper - TimeLower));
836  double Width2 = pow(Width, 2);
837 
838  HitWires.at(ViewIndex).push_back(WireCoord);
839  HitTimes.at(ViewIndex).push_back(TimeCoord);
840  HitWidths.at(ViewIndex).push_back(fabs(0.5 * (TimeUpper - TimeLower)));
841 
842  MeanWireCoord.at(ViewIndex) += WireCoord;
843  MeanTimeCoord.at(ViewIndex) += TimeCoord;
844 
845  // Elements for LS
846  x.at(ViewIndex) += WireCoord / Width2;
847  y.at(ViewIndex) += TimeCoord / Width2;
848  xy.at(ViewIndex) += (TimeCoord * WireCoord) / Width2;
849  xx.at(ViewIndex) += (WireCoord * WireCoord) / Width2;
850  yy.at(ViewIndex) += (TimeCoord * TimeCoord) / Width2;
851  sig.at(ViewIndex) += 1. / Width2;
852  N.at(ViewIndex)++;
853  }
854 
855  ViewRMS.clear();
856  ViewRMS.resize(3);
857  std::vector<double> ViewGrad(3);
858  std::vector<double> ViewOffset(3);
859 
860  for (size_t n = 0; n != 3; ++n) {
861  MeanWireCoord[n] /= N[n];
862  MeanTimeCoord[n] /= N[n];
863 
864  double BigN = 1000000;
865  double SmallN = 1. / BigN;
866 
867  if (N[n] > 2) {
868  double Numerator = (y[n] / sig[n] - xy[n] / x[n]);
869  double Denominator = (x[n] / sig[n] - xx[n] / x[n]);
870  if (fabs(Denominator) > SmallN)
871  ViewGrad.at(n) = Numerator / Denominator;
872  else
873  ViewGrad[n] = BigN;
874  }
875  else if (N[n] == 2)
876  ViewGrad[n] = xy[n] / xx[n];
877  else
878  ViewGrad[n] = BigN;
879 
880  ViewOffset.at(n) = (y[n] - ViewGrad[n] * x[n]) / sig[n];
881  ViewRMS.at(n) = pow((yy[n] + pow(ViewGrad[n], 2) * xx[n] + pow(ViewOffset[n], 2) * sig[n] -
882  2 * ViewGrad[n] * xy[n] - 2 * ViewOffset[n] * y[n] +
883  2 * ViewGrad[n] * ViewOffset[n] * x[n]) /
884  N[n],
885  0.5);
886  // Make RMS rotation perp to track
887  if (ViewGrad.at(n) != 0) ViewRMS[n] *= sin(atan(1. / ViewGrad.at(n)));
888  }
889 
890  for (size_t n = 0; n != 3; ++n) {
891  size_t n1 = (n + 1) % 3;
892  size_t n2 = (n + 2) % 3;
893  if ((N[n] <= N[n1]) && (N[n] <= N[n2])) {
894 
895  if (N[n1] < N[n2]) { std::swap(n1, n2); }
896  if ((N[n1] == 0) || (N[n2] == 0)) continue;
897 
898  Direction =
899  (fXDir + fPitchDir[n1] * (1. / ViewGrad[n1]) +
900  fWireDir[n1] *
901  (((1. / ViewGrad[n2]) - fPitchDir[n1].Dot(fPitchDir[n2]) * (1. / ViewGrad[n1])) /
902  fWireDir[n1].Dot(fPitchDir[n2])))
903  .Unit();
904 
905  /*
906  Center2D[n] =
907  fXDir * 0.5 * (MeanTimeCoord[n1]+MeanTimeCoord[n2])
908  + fPitchDir[n1] * (MeanWireCoord[n1] + fWireZeroOffset[n1])
909  + fWireDir[n1] * ( ((MeanWireCoord[n2] + fWireZeroOffset[n2]) - ( MeanWireCoord[n1] + fWireZeroOffset[n1] )*fPitchDir[n1].Dot(fPitchDir[n2]))/(fPitchDir[n2].Dot(fWireDir[n1])) );
910  */
911 
912  double TimeCoord = 0.5 * (MeanTimeCoord[n1] + MeanTimeCoord[n2]);
913  double WireCoordIn1 = (TimeCoord - ViewOffset[n1]) / ViewGrad[n1] + fWireZeroOffset[n1];
914  double WireCoordIn2 = (TimeCoord - ViewOffset[n2]) / ViewGrad[n2] + fWireZeroOffset[n2];
915 
916  Center = fXDir * TimeCoord + fPitchDir[n1] * WireCoordIn1 +
917  fWireDir[n1] * ((WireCoordIn2 - WireCoordIn1 * fPitchDir[n1].Dot(fPitchDir[n2])) /
918  (fPitchDir[n2].Dot(fWireDir[n1])));
919 
920  ViewRMS[n] = -fabs(ViewRMS[n]);
921  ViewRMS[n1] = fabs(ViewRMS[n1]);
922  ViewRMS[n2] = fabs(ViewRMS[n2]);
923 
924  break;
925  }
926  }
927  }
928 
929  //-----------------------------------------------
930  void
932  {
933  art::ServiceHandle<geo::Geometry const> geom;
934 
935  // Total number of channels in the detector
936  fNChannels = geom->Nchannels();
937 
938  // Find pitch of each wireplane
939  fPitches.resize(3);
940  fPitches.at(0) = fabs(geom->WirePitch(geo::kU));
941  fPitches.at(1) = fabs(geom->WirePitch(geo::kV));
942  fPitches.at(2) = fabs(geom->WirePitch(geo::kW));
943 
944  // Setup basis vectors
945  fXDir = TVector3(1, 0, 0);
946  fYDir = TVector3(0, 1, 0);
947  fZDir = TVector3(0, 0, 1);
948 
949  fWireDir.resize(3);
950  fPitchDir.resize(3);
951  fWireZeroOffset.resize(3);
952 
953  double xyzStart1[3], xyzStart2[3];
954  double xyzEnd1[3], xyzEnd2[3];
955 
956  // Calculate wire coordinate systems
957  for (size_t n = 0; n != 3; ++n) {
958  geom->WireEndPoints(0, 0, n, 0, xyzStart1, xyzEnd1);
959  geom->WireEndPoints(0, 0, n, 1, xyzStart2, xyzEnd2);
960  fWireDir[n] =
961  TVector3(xyzEnd1[0] - xyzStart1[0], xyzEnd1[1] - xyzStart1[1], xyzEnd1[2] - xyzStart1[2])
962  .Unit();
963  fPitchDir[n] = fWireDir[n].Cross(fXDir).Unit();
964  if (fPitchDir[n].Dot(TVector3(
965  xyzEnd2[0] - xyzEnd1[0], xyzEnd2[1] - xyzEnd1[1], xyzEnd2[2] - xyzEnd1[2])) < 0)
966  fPitchDir[n] = -fPitchDir[n];
967 
968  fWireZeroOffset[n] =
969  xyzEnd1[0] * fPitchDir[n][0] + xyzEnd1[1] * fPitchDir[n][1] + xyzEnd1[2] * fPitchDir[n][2];
970  }
971  }
972 
973  //-----------------------------------------------
974 
975  std::vector<recob::Seed>
977  detinfo::DetectorClocksData const& clockData,
979  art::PtrVector<recob::Hit> const& Hits,
980  std::vector<art::PtrVector<recob::Hit>>& HitCatalogue,
981  unsigned int StopAfter) const
982  {
983  std::vector<recob::Seed> ReturnVec;
984  return FindSeeds(clockData, detProp, Hits, HitCatalogue, StopAfter);
985  }
986 
987  //---------------------------------------------
988 
989  std::vector<std::vector<recob::Seed>>
991  detinfo::DetectorClocksData const& clockData,
993  std::vector<std::vector<art::PtrVector<recob::Hit>>> const& SortedHits,
994  std::vector<std::vector<art::PtrVector<recob::Hit>>>& HitsPerSeed,
995  unsigned int StopAfter) const
996  {
997 
998  std::vector<std::vector<recob::Seed>> ReturnVec;
999 
1000  // This piece of code looks detector specific, but its not -
1001  // it also works for 2 planes, but one vector is empty.
1002 
1003  if (!(fSptalg->enableU() && fSptalg->enableV() && fSptalg->enableW()))
1004  mf::LogWarning("BezierTrackerModule")
1005  << "Warning: SpacePointAlg is does not have three views enabled. This may cause unexpected "
1006  "behaviour in the bezier tracker.";
1007 
1008  try {
1009  for (std::vector<art::PtrVector<recob::Hit>>::const_iterator itU =
1010  SortedHits.at(geo::kU).begin();
1011  itU != SortedHits.at(geo::kU).end();
1012  ++itU)
1013  for (std::vector<art::PtrVector<recob::Hit>>::const_iterator itV =
1014  SortedHits.at(geo::kV).begin();
1015  itV != SortedHits.at(geo::kV).end();
1016  ++itV)
1017  for (std::vector<art::PtrVector<recob::Hit>>::const_iterator itW =
1018  SortedHits.at(geo::kW).begin();
1019  itW != SortedHits.at(geo::kW).end();
1020  ++itW) {
1021  art::PtrVector<recob::Hit> HitsThisComboFlat;
1022 
1023  if (fSptalg->enableU())
1024  for (size_t i = 0; i != itU->size(); ++i)
1025  HitsThisComboFlat.push_back(itU->at(i));
1026 
1027  if (fSptalg->enableV())
1028  for (size_t i = 0; i != itV->size(); ++i)
1029  HitsThisComboFlat.push_back(itV->at(i));
1030 
1031  if (fSptalg->enableW())
1032  for (size_t i = 0; i != itW->size(); ++i)
1033  HitsThisComboFlat.push_back(itW->at(i));
1034 
1035  std::vector<art::PtrVector<recob::Hit>> CataloguedHits;
1036 
1037  std::vector<recob::Seed> Seeds =
1038  FindSeeds(clockData, detProp, HitsThisComboFlat, CataloguedHits, StopAfter);
1039 
1040  // Add this harvest to return vectors
1041  HitsPerSeed.push_back(CataloguedHits);
1042  ReturnVec.push_back(Seeds);
1043 
1044  // Tidy up
1045  CataloguedHits.clear();
1046  Seeds.clear();
1047  }
1048  }
1049  catch (...) {
1050  mf::LogWarning("SeedFinderTrackerModule")
1051  << " bailed during hit map lookup - have you enabled all 3 planes?";
1052  ReturnVec.push_back(std::vector<recob::Seed>());
1053  }
1054 
1055  return ReturnVec;
1056  }
1057 
1058 }
std::vector< double > fPitches
float Length(const PFPStruct &pfp)
Definition: PFPUtils.cxx:3304
SeedFinderAlgorithm(const fhicl::ParameterSet &pset)
static std::string ViewName(geo::View_t view)
Returns the name of the specified view.
Definition: PlaneGeo.cxx:763
process_name opflash particleana ie x
bool IsValid() const
Definition: Seed.cxx:70
enum geo::_plane_proj View_t
Enumerate the possible plane projections.
Planes which measure V.
Definition: geo_types.h:130
Declaration of signal hit object.
EResult err(const char *call)
void GetPoint(double *Pt, double *Err) const
Definition: Seed.cxx:108
void GetHitDistAndProj(detinfo::DetectorPropertiesData const &detProp, recob::Seed const &ASeed, art::Ptr< recob::Hit > const &AHit, double &disp, double &s) const
std::size_t size(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:561
void reconfigure(fhicl::ParameterSet const &pset)
bool enableV() const noexcept
recob::Seed FindSeedAtEnd(detinfo::DetectorPropertiesData const &detProp, std::vector< recob::SpacePoint > const &, std::vector< char > &, std::vector< int > &, art::PtrVector< recob::Hit > const &HitsFlat, std::vector< std::vector< std::vector< int >>> &OrgHits) const
const art::PtrVector< recob::Hit > & getAssociatedHits(const recob::SpacePoint &spt) const
void ConsolidateSeed(detinfo::DetectorPropertiesData const &detProp, recob::Seed &TheSeed, art::PtrVector< recob::Hit > const &, std::vector< char > &HitStatus, std::vector< std::vector< std::vector< int >>> &OrgHits, bool Extend) const
std::map< int, art::Ptr< recob::Hit > > HitMap
while getopts h
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
Planes which measure U.
Definition: geo_types.h:129
auto counter(T begin, T end)
Returns an object to iterate values from begin to end in a range-for loop.
Definition: counter.h:285
process_name opflash particleana ie ie y
void SetPoint(double *Pt, double *Err)
Definition: Seed.cxx:144
void makeSpacePoints(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const art::PtrVector< recob::Hit > &hits, std::vector< recob::SpacePoint > &spts) const
bool enableU() const noexcept
void GetCenterAndDirection(detinfo::DetectorPropertiesData const &detProp, art::PtrVector< recob::Hit > const &HitsFlat, std::vector< int > &HitsToUse, TVector3 &Center, TVector3 &Direction, std::vector< double > &ViewRMS, std::vector< int > &HitsPerView) const
std::vector< recob::Seed > FindSeeds(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, art::PtrVector< recob::Hit > const &HitsFlat, std::vector< art::PtrVector< recob::Hit >> &CataloguedHits, unsigned int StopAfter) const
tuple dir
Definition: dropbox.py:28
std::vector< recob::Seed > GetSeedsFromUnSortedHits(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, art::PtrVector< recob::Hit > const &, std::vector< art::PtrVector< recob::Hit >> &, unsigned int StopAfter=0) const
double ConvertTicksToX(double ticks, int p, int t, int c) const
art::PtrVector< recob::Hit > Hits
void clearHitMap() const
Encapsulate the construction of a single detector plane.
Contains all timing reference information for the detector.
constexpr double dist(const TReal *x, const TReal *y, const unsigned int dimension)
std::vector< TVector3 > fWireDir
then echo File list $list not found else cat $list while read file do echo $file sed s
Definition: file_to_url.sh:60
process_name largeant stream1 can override from command line with o or output physics producers generator N
bool enableW() const noexcept
std::vector< TVector3 > fPitchDir
Planes which measure W (third view for Bo, MicroBooNE, etc).
Definition: geo_types.h:131
Algorithm for generating space points from hits.
std::set< art::Ptr< recob::Hit > > HitList
void SetValidity(bool Validity)
Definition: Seed.cxx:90
esac echo uname r
std::vector< std::vector< recob::Seed > > GetSeedsFromSortedHits(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, std::vector< std::vector< art::PtrVector< recob::Hit >>> const &SortedHits, std::vector< std::vector< art::PtrVector< recob::Hit >>> &HitsPerSeed, unsigned int StopAfter=0) const
void GetDirection(double *Dir, double *Err) const
Definition: Seed.cxx:98
std::vector< double > fWireZeroOffset
art framework interface to geometry description
auto const detProp
double GetLength() const
Definition: Seed.cxx:155
void SetDirection(double *Dir, double *Err)
Definition: Seed.cxx:133
std::vector< double > fMaxViewRMS