All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ShowerIncrementalTrackHitFinder_tool.cc
Go to the documentation of this file.
1 //############################################################################
2 //### Name: ShowerIncrementalTrackHitFinder ###
3 //### Author: Dom Barker ###
4 //### Date: 13.05.19 ###
5 //### Description: Tool to incrementally add space points to the initial ###
6 //### track space points until the residuals blow up ###
7 //############################################################################
8 
9 //Framework Includes
10 #include "art/Utilities/ToolMacros.h"
11 
12 //LArSoft Includes
20 
21 //Root Includes
22 #include "TCanvas.h"
23 #include "TGraph2D.h"
24 #include "TPrincipal.h"
25 
26 namespace ShowerRecoTools {
27 
29 
30  public:
31  ShowerIncrementalTrackHitFinder(const fhicl::ParameterSet& pset);
32 
33  //Generic Direction Finder
34  int CalculateElement(const art::Ptr<recob::PFParticle>& pfparticle,
35  art::Event& Event,
36  reco::shower::ShowerElementHolder& ShowerEleHolder) override;
37 
38  private:
39  std::vector<art::Ptr<recob::SpacePoint>> RunIncrementalSpacePointFinder(
40  const art::Event& Event,
41  std::vector<art::Ptr<recob::SpacePoint>> const& sps,
42  const art::FindManyP<recob::Hit>& fmh);
43 
44  void PruneFrontOfSPSPool(std::vector<art::Ptr<recob::SpacePoint>>& sps_pool,
45  std::vector<art::Ptr<recob::SpacePoint>> const& initial_track);
46 
47  void PruneTrack(std::vector<art::Ptr<recob::SpacePoint>>& initial_track);
48 
49  void AddSpacePointsToSegment(std::vector<art::Ptr<recob::SpacePoint>>& segment,
50  std::vector<art::Ptr<recob::SpacePoint>>& sps_pool,
51  size_t num_sps_to_take);
52 
53  bool IsSegmentValid(std::vector<art::Ptr<recob::SpacePoint>> const& segment);
54 
57  std::vector<art::Ptr<recob::SpacePoint>>& segment,
58  std::vector<art::Ptr<recob::SpacePoint>>& sps_pool,
59  const art::FindManyP<recob::Hit>& fmh,
60  double current_residual);
61 
63  const detinfo::DetectorPropertiesData& detProp,
64  std::vector<art::Ptr<recob::SpacePoint>>& segment,
65  const art::FindManyP<recob::Hit>& fmh);
66 
68  const detinfo::DetectorPropertiesData& detProp,
69  std::vector<art::Ptr<recob::SpacePoint>>& segment,
70  const art::FindManyP<recob::Hit>& fmh,
71  int& max_residual_point);
72 
74  const detinfo::DetectorClocksData& clockData,
75  const detinfo::DetectorPropertiesData& detProp,
76  std::vector<art::Ptr<recob::SpacePoint>>& segment,
77  std::vector<art::Ptr<recob::SpacePoint>>& reduced_sps_pool,
78  const art::FindManyP<recob::Hit>& fmh,
79  double current_residual);
80 
81  bool
82  IsResidualOK(double new_residual, double current_residual)
83  {
84  return new_residual - current_residual < fMaxResidualDiff;
85  };
86  bool
87  IsResidualOK(double new_residual, double current_residual, size_t no_sps)
88  {
89  return (new_residual - current_residual < fMaxResidualDiff &&
90  new_residual / no_sps < fMaxAverageResidual);
91  };
92  bool
93  IsResidualOK(double residual, size_t no_sps)
94  {
95  return residual / no_sps < fMaxAverageResidual;
96  }
97 
98  double CalculateResidual(std::vector<art::Ptr<recob::SpacePoint>>& sps,
99  TVector3& PCAEigenvector,
100  TVector3& TrackPosition);
101 
102  double CalculateResidual(std::vector<art::Ptr<recob::SpacePoint>>& sps,
103  TVector3& PCAEigenvector,
104  TVector3& TrackPosition,
105  int& max_residual_point);
106 
107  //Function to calculate the shower direction using a charge weight 3D PCA calculation.
108  TVector3 ShowerPCAVector(std::vector<art::Ptr<recob::SpacePoint>>& sps);
109 
110  TVector3 ShowerPCAVector(const detinfo::DetectorClocksData& clockData,
111  const detinfo::DetectorPropertiesData& detProp,
112  const std::vector<art::Ptr<recob::SpacePoint>>& sps,
113  const art::FindManyP<recob::Hit>& fmh);
114 
115  std::vector<art::Ptr<recob::SpacePoint>> CreateFakeShowerTrajectory(TVector3 start_position,
116  TVector3 start_direction);
117  std::vector<art::Ptr<recob::SpacePoint>> CreateFakeSPLine(TVector3 start_position,
118  TVector3 start_direction,
119  int npoints);
120  void RunTestOfIncrementalSpacePointFinder(const art::Event& Event,
121  const art::FindManyP<recob::Hit>& dud_fmh);
122 
123  void MakeTrackSeed(const detinfo::DetectorClocksData& clockData,
124  const detinfo::DetectorPropertiesData& detProp,
125  std::vector<art::Ptr<recob::SpacePoint>>& segment,
126  const art::FindManyP<recob::Hit>& fmh);
127 
128  //Services
129  art::InputTag fPFParticleLabel;
130  int fVerbose;
139  bool fRunTest;
147  };
148 
150  : IShowerTool(pset.get<fhicl::ParameterSet>("BaseTools"))
151  , fPFParticleLabel(pset.get<art::InputTag>("PFParticleLabel"))
152  , fVerbose(pset.get<int>("Verbose"))
153  , fUseShowerDirection(pset.get<bool>("UseShowerDirection"))
154  , fChargeWeighted(pset.get<bool>("ChargeWeighted"))
155  , fForwardHitsOnly(pset.get<bool>("ForwardHitsOnly"))
156  , fMaxResidualDiff(pset.get<float>("MaxResidualDiff"))
157  , fMaxAverageResidual(pset.get<float>("MaxAverageResidual"))
158  , fStartFitSize(pset.get<int>("StartFitSize"))
159  , fNMissPoints(pset.get<int>("NMissPoints"))
160  , fTrackMaxAdjacentSPDistance(pset.get<float>("TrackMaxAdjacentSPDistance"))
161  , fRunTest(0)
162  , fMakeTrackSeed(pset.get<bool>("MakeTrackSeed"))
163  , fStartDistanceCut(pset.get<float>("StartDistanceCut"))
164  , fDistanceCut(pset.get<float>("DistanceCut"))
165  , fShowerStartPositionInputLabel(pset.get<std::string>("ShowerStartPositionInputLabel"))
166  , fShowerDirectionInputLabel(pset.get<std::string>("ShowerDirectionInputLabel"))
167  ,
168 
169  fInitialTrackHitsOutputLabel(pset.get<std::string>("InitialTrackHitsOutputLabel"))
170  , fInitialTrackSpacePointsOutputLabel(
171  pset.get<std::string>("InitialTrackSpacePointsOutputLabel"))
172  {
173  if (fStartFitSize == 0) {
174  throw cet::exception("ShowerIncrementalTrackHitFinder")
175  << "We cannot make a track if you don't gives us at leats one hit. Change fStartFitSize "
176  "please to something sensible";
177  }
178  }
179 
180  int
182  const art::Ptr<recob::PFParticle>& pfparticle,
183  art::Event& Event,
184  reco::shower::ShowerElementHolder& ShowerEleHolder)
185  {
186 
187  //This is all based on the shower vertex being known. If it is not lets not do the track
188  if (!ShowerEleHolder.CheckElement(fShowerStartPositionInputLabel)) {
189  if (fVerbose)
190  mf::LogError("ShowerIncrementalTrackHitFinder")
191  << "Start position not set, returning " << std::endl;
192  return 1;
193  }
194 
195  // Get the assocated pfParicle Handle
196  auto const pfpHandle = Event.getValidHandle<std::vector<recob::PFParticle>>(fPFParticleLabel);
197 
198  // Get the spacepoint - PFParticle assn
199  const art::FindManyP<recob::SpacePoint>& fmspp =
200  ShowerEleHolder.GetFindManyP<recob::SpacePoint>(pfpHandle, Event, fPFParticleLabel);
201 
202  // Get the spacepoints
203  auto const spHandle = Event.getValidHandle<std::vector<recob::SpacePoint>>(fPFParticleLabel);
204 
205  // Get the hits associated with the space points
206  const art::FindManyP<recob::Hit>& fmh =
207  ShowerEleHolder.GetFindManyP<recob::Hit>(spHandle, Event, fPFParticleLabel);
208 
209  // Get the SpacePoints
210  std::vector<art::Ptr<recob::SpacePoint>> spacePoints = fmspp.at(pfparticle.key());
211 
212  //We cannot progress with no spacepoints.
213  if (spacePoints.empty()) {
214  if (fVerbose)
215  mf::LogError("ShowerIncrementalTrackHitFinder")
216  << "No space points, returning " << std::endl;
217  return 1;
218  }
219 
220  TVector3 ShowerStartPosition = {-999, -999, -999};
221  ShowerEleHolder.GetElement(fShowerStartPositionInputLabel, ShowerStartPosition);
222 
223  //Decide if the you want to use the direction of the shower or make one.
224  if (fUseShowerDirection) {
225 
226  if (!ShowerEleHolder.CheckElement(fShowerDirectionInputLabel)) {
227  if (fVerbose)
228  mf::LogError("ShowerIncrementalTrackHitFinder")
229  << "Direction not set, returning " << std::endl;
230  return 1;
231  }
232 
233  TVector3 ShowerDirection = {-999, -999, -999};
234  ShowerEleHolder.GetElement(fShowerDirectionInputLabel, ShowerDirection);
235 
236  //Order the spacepoints
238  spacePoints, ShowerStartPosition, ShowerDirection);
239  //Remove the back hits if requird.
240  if (fForwardHitsOnly) {
241  int back_sps = 0;
242  for (auto spacePoint : spacePoints) {
244  spacePoint, ShowerStartPosition, ShowerDirection);
245  if (proj < 0) { ++back_sps; }
246  if (proj > 0) { break; }
247  }
248  spacePoints.erase(spacePoints.begin(), spacePoints.begin() + back_sps);
249  }
250  }
251  else {
252  //Order the spacepoint using the magnitude away from the vertex
254  ShowerStartPosition);
255  }
256 
257  //Remove the first x spacepoints
258  int frontsp = 0;
259  for (auto spacePoint : spacePoints) {
260  double dist =
261  (IShowerTool::GetLArPandoraShowerAlg().SpacePointPosition(spacePoint) - ShowerStartPosition)
262  .Mag();
263  if (dist > fStartDistanceCut) { break; }
264  ++frontsp;
265  }
266  spacePoints.erase(spacePoints.begin(), spacePoints.begin() + frontsp);
267 
268  //Bin anything above x cm
269  int sp_iter = 0;
270  for (auto spacePoint : spacePoints) {
271  double dist =
272  (IShowerTool::GetLArPandoraShowerAlg().SpacePointPosition(spacePoint) - ShowerStartPosition)
273  .Mag();
274  if (dist > fDistanceCut) { break; }
275  ++sp_iter;
276  }
277  spacePoints.erase(spacePoints.begin() + sp_iter, spacePoints.end());
278 
279  if (spacePoints.size() < 3) {
280  if (fVerbose)
281  mf::LogError("ShowerIncrementalTrackHitFinder")
282  << "Not enough spacepoints bailing" << std::endl;
283  return 1;
284  }
285 
286  //Create fake hits and test the algorithm
288 
289  //Actually runt he algorithm.
290  std::vector<art::Ptr<recob::SpacePoint>> track_sps =
291  RunIncrementalSpacePointFinder(Event, spacePoints, fmh);
292 
293  // Get the hits associated to the space points and seperate them by planes
294  std::vector<art::Ptr<recob::Hit>> trackHits;
295  for (auto const& spacePoint : track_sps) {
296  std::vector<art::Ptr<recob::Hit>> hits = fmh.at(spacePoint.key());
297  for (auto const& hit : hits) {
298  trackHits.push_back(hit);
299  }
300  }
301 
302  //Add to the holder
303  ShowerEleHolder.SetElement(trackHits, fInitialTrackHitsOutputLabel);
304  ShowerEleHolder.SetElement(track_sps, fInitialTrackSpacePointsOutputLabel);
305 
306  return 0;
307  }
308 
309  TVector3
311  {
312 
313  //Initialise the the PCA.
314  TPrincipal* pca = new TPrincipal(3, "");
315 
316  //Normalise the spacepoints, charge weight and add to the PCA.
317  for (auto& sp : sps) {
318 
319  TVector3 sp_position = IShowerTool::GetLArPandoraShowerAlg().SpacePointPosition(sp);
320 
321  double sp_coord[3];
322  sp_coord[0] = sp_position.X();
323  sp_coord[1] = sp_position.Y();
324  sp_coord[2] = sp_position.Z();
325 
326  //Add to the PCA
327  pca->AddRow(sp_coord);
328  }
329 
330  //Evaluate the PCA
331  pca->MakePrincipals();
332 
333  //Get the Eigenvectors.
334  const TMatrixD* Eigenvectors = pca->GetEigenVectors();
335 
336  TVector3 Eigenvector = {(*Eigenvectors)[0][0], (*Eigenvectors)[1][0], (*Eigenvectors)[2][0]};
337 
338  delete pca;
339 
340  return Eigenvector;
341  }
342 
343  //Function to calculate the shower direction using a charge weight 3D PCA calculation.
344  TVector3
346  const detinfo::DetectorClocksData& clockData,
348  const std::vector<art::Ptr<recob::SpacePoint>>& sps,
349  const art::FindManyP<recob::Hit>& fmh)
350  {
351 
352  //Initialise the the PCA.
353  TPrincipal* pca = new TPrincipal(3, "");
354 
355  float TotalCharge = 0;
356 
357  //Normalise the spacepoints, charge weight and add to the PCA.
358  for (auto& sp : sps) {
359 
360  TVector3 sp_position = IShowerTool::GetLArPandoraShowerAlg().SpacePointPosition(sp);
361 
362  float wht = 1;
363 
364  if (fChargeWeighted) {
365 
366  //Get the charge.
367  float Charge = IShowerTool::GetLArPandoraShowerAlg().SpacePointCharge(sp, fmh);
368  // std::cout << "Charge: " << Charge << std::endl;
369 
370  //Get the time of the spacepoint
371  float Time = IShowerTool::GetLArPandoraShowerAlg().SpacePointTime(sp, fmh);
372 
373  //Correct for the lifetime at the moment.
374  Charge *= std::exp((sampling_rate(clockData) * Time) / (detProp.ElectronLifetime() * 1e3));
375  // std::cout << "Charge: "<< Charge << std::endl;
376 
377  //Charge Weight
378  wht *= std::sqrt(Charge / TotalCharge);
379  }
380 
381  double sp_coord[3];
382  sp_coord[0] = sp_position.X() * wht;
383  sp_coord[1] = sp_position.Y() * wht;
384  sp_coord[2] = sp_position.Z() * wht;
385 
386  //Add to the PCA
387  pca->AddRow(sp_coord);
388  }
389 
390  //Evaluate the PCA
391  pca->MakePrincipals();
392 
393  //Get the Eigenvectors.
394  const TMatrixD* Eigenvectors = pca->GetEigenVectors();
395 
396  TVector3 Eigenvector = {(*Eigenvectors)[0][0], (*Eigenvectors)[1][0], (*Eigenvectors)[2][0]};
397 
398  delete pca;
399 
400  return Eigenvector;
401  }
402 
403  //Function to remove the spacepoint with the highest residual until we have a track which matches the
404  //residual criteria.
405  void
408  std::vector<art::Ptr<recob::SpacePoint>>& segment,
409  const art::FindManyP<recob::Hit>& fmh)
410  {
411 
412  bool ok = true;
413 
414  int maxresidual_point = 0;
415 
416  //Check the residual
417  double residual =
418  FitSegmentAndCalculateResidual(clockData, detProp, segment, fmh, maxresidual_point);
419 
420  //Is it okay
421  ok = IsResidualOK(residual, segment.size());
422 
423  //Remove points until we can fit a track.
424  while (!ok && segment.size() != 1) {
425 
426  //Remove the point with the highest residual
427  for (auto sp = segment.begin(); sp != segment.end(); ++sp) {
428  if (sp->key() == (unsigned)maxresidual_point) {
429  segment.erase(sp);
430  break;
431  }
432  }
433 
434  //Check the residual
435  double residual =
436  FitSegmentAndCalculateResidual(clockData, detProp, segment, fmh, maxresidual_point);
437 
438  //Is it okay
439  ok = IsResidualOK(residual, segment.size());
440  }
441  }
442 
443  std::vector<art::Ptr<recob::SpacePoint>>
445  const art::Event& Event,
446  std::vector<art::Ptr<recob::SpacePoint>> const& sps,
447  const art::FindManyP<recob::Hit>& fmh)
448  {
449 
450  auto const clockData =
451  art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(Event);
452  auto const detProp =
453  art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(Event, clockData);
454 
455  //Create space point pool (yes we are copying the input vector because we're going to twiddle with it
456  std::vector<art::Ptr<recob::SpacePoint>> sps_pool = sps;
457  std::vector<art::Ptr<recob::SpacePoint>> initial_track;
458  std::vector<art::Ptr<recob::SpacePoint>> track_segment_copy;
459 
460  while (sps_pool.size() > 0) {
461  //PruneFrontOfSPSPool(sps_pool, initial_track);
462 
463  std::vector<art::Ptr<recob::SpacePoint>> track_segment;
464  AddSpacePointsToSegment(track_segment, sps_pool, (size_t)(fStartFitSize));
465  if (!IsSegmentValid(track_segment)) {
466  //Clear the pool and lets leave this place
467  sps_pool.clear();
468  break;
469  }
470 
471  //Lets really try to make the initial track seed.
472  if (fMakeTrackSeed && sps_pool.size() + fStartFitSize == sps.size()) {
473  MakeTrackSeed(clockData, detProp, track_segment, fmh);
474  if (track_segment.empty()) break;
475 
476  track_segment_copy = track_segment;
477  }
478 
479  //A sleight of hand coming up. We are going to move the last sp from the segment back into the pool so
480  //that it makes kick starting the recursion easier (sneaky)
481  //TODO defend against segments that are too small for this to work (I dunno who is running the alg with
482  //fStartFitMinSize==0 but whatever
483  sps_pool.insert(sps_pool.begin(), track_segment.back());
484  track_segment.pop_back();
485  double current_residual = 0;
486  size_t initial_segment_size = track_segment.size();
487 
488  IncrementallyFitSegment(clockData, detProp, track_segment, sps_pool, fmh, current_residual);
489 
490  //Check if the track has grown in size at all
491  if (initial_segment_size == track_segment.size()) {
492  //The incremental fitter could not grow th track at all. SAD!
493  //Clear the pool and let's get out of here
494  sps_pool.clear();
495  break;
496  }
497  else {
498  //We did some good fitting and everyone is really happy with it
499  //Let's store all of the hits in the final space point vector
500  AddSpacePointsToSegment(initial_track, track_segment, track_segment.size());
501  }
502  }
503 
504  //If we have failed then no worry we have the seed. We shall just give those points.
505  if (fMakeTrackSeed && initial_track.empty()) initial_track = track_segment_copy;
506 
507  //Runt the algorithm that attepmts to remove hits too far away from the track.
508  PruneTrack(initial_track);
509 
510  return initial_track;
511  }
512 
513  void
515  std::vector<art::Ptr<recob::SpacePoint>>& sps_pool,
516  std::vector<art::Ptr<recob::SpacePoint>> const& initial_track)
517  {
518 
519  //If the initial track is empty then there is no pruning to do
520  if (initial_track.empty()) return;
522  initial_track.back(), sps_pool.front());
523  while (distance > 1 && sps_pool.size() > 0) {
524  sps_pool.erase(sps_pool.begin());
526  initial_track.back(), sps_pool.front());
527  }
528  return;
529  }
530 
531  void
533  std::vector<art::Ptr<recob::SpacePoint>>& initial_track)
534  {
535 
536  if (initial_track.empty()) return;
537  std::vector<art::Ptr<recob::SpacePoint>>::iterator sps_it = initial_track.begin();
538  while (sps_it != std::next(initial_track.end(), -1)) {
539  std::vector<art::Ptr<recob::SpacePoint>>::iterator next_sps_it = std::next(sps_it, 1);
540  double distance =
542  if (distance > fTrackMaxAdjacentSPDistance) { initial_track.erase(next_sps_it); }
543  else {
544  sps_it++;
545  }
546  }
547  return;
548  }
549 
550  void
552  std::vector<art::Ptr<recob::SpacePoint>>& segment,
553  std::vector<art::Ptr<recob::SpacePoint>>& sps_pool,
554  size_t num_sps_to_take)
555  {
556  size_t new_segment_size = segment.size() + num_sps_to_take;
557  while (segment.size() < new_segment_size && sps_pool.size() > 0) {
558  segment.push_back(sps_pool[0]);
559  sps_pool.erase(sps_pool.begin());
560  }
561  return;
562  }
563 
564  bool
566  std::vector<art::Ptr<recob::SpacePoint>> const& segment)
567  {
568  bool ok = true;
569  if (segment.size() < (size_t)(fStartFitSize)) return !ok;
570 
571  return ok;
572  }
573 
574  bool
576  const detinfo::DetectorClocksData& clockData,
578  std::vector<art::Ptr<recob::SpacePoint>>& segment,
579  std::vector<art::Ptr<recob::SpacePoint>>& sps_pool,
580  const art::FindManyP<recob::Hit>& fmh,
581  double current_residual)
582  {
583 
584  bool ok = true;
585  //Firstly, are there any space points left???
586  if (sps_pool.empty()) return !ok;
587  //Fit the current line
588  current_residual = FitSegmentAndCalculateResidual(clockData, detProp, segment, fmh);
589  //Take a space point from the pool and plonk it onto the seggieweggie
590  AddSpacePointsToSegment(segment, sps_pool, 1);
591  //Fit again
592  double residual = FitSegmentAndCalculateResidual(clockData, detProp, segment, fmh);
593 
594  ok = IsResidualOK(residual, current_residual, segment.size());
595  if (!ok) {
596  //Create a sub pool of space points to pass to the refitter
597  std::vector<art::Ptr<recob::SpacePoint>> sub_sps_pool;
598  AddSpacePointsToSegment(sub_sps_pool, sps_pool, fNMissPoints);
599  //We'll need an additional copy of this pool, as we will need the space points if we have to start a new
600  //segment later, but all of the funtionality drains the pools during use
601  std::vector<art::Ptr<recob::SpacePoint>> sub_sps_pool_cache = sub_sps_pool;
602  //The most recently added SP to the segment is bad but it will get thrown away by RecursivelyReplaceLastSpacePointAndRefit
603  //It's possible that we will need it if we end up forming an entirely new line from scratch, so
604  //add the bad SP to the front of the cache
605  sub_sps_pool_cache.insert(sub_sps_pool_cache.begin(), segment.back());
607  clockData, detProp, segment, sub_sps_pool, fmh, current_residual);
608  if (ok) {
609  //The refitting may have dropped a couple of points but it managed to find a point that kept the residual
610  //at a sensible value.
611  //Add the remaining SPS in the reduced pool back t othe start of the larger pool
612  while (sub_sps_pool.size() > 0) {
613  sps_pool.insert(sps_pool.begin(), sub_sps_pool.back());
614  sub_sps_pool.pop_back();
615  }
616  //We'll need the latest residual now that we've managed to refit the track
617  residual = FitSegmentAndCalculateResidual(clockData, detProp, segment, fmh);
618  }
619  else {
620  //All of the space points in the reduced pool could not sensibly refit the track. The reduced pool will be
621  //empty so move all of the cached space points back into the main pool
622  // std::cout<<"The refitting was NOT a success, dumping all " << sub_sps_pool_cache.size() << " sps back into the pool" << std::endl;
623  while (sub_sps_pool_cache.size() > 0) {
624  sps_pool.insert(sps_pool.begin(), sub_sps_pool_cache.back());
625  sub_sps_pool_cache.pop_back();
626  }
627  //The bad point is still on the segment, so remove it
628  segment.pop_back();
629  return !ok;
630  }
631  }
632 
633  //Update the residual
634  current_residual = residual;
635 
636  //Round and round we go
637  //NOBODY GETS OFF MR BONES WILD RIDE
638  return IncrementallyFitSegment(clockData, detProp, segment, sps_pool, fmh, current_residual);
639  }
640 
641  double
643  const detinfo::DetectorClocksData& clockData,
645  std::vector<art::Ptr<recob::SpacePoint>>& segment,
646  const art::FindManyP<recob::Hit>& fmh)
647  {
648 
649  TVector3 primary_axis;
650  if (fChargeWeighted)
651  primary_axis = ShowerPCAVector(clockData, detProp, segment, fmh);
652  else
653  primary_axis = ShowerPCAVector(segment);
654 
655  TVector3 segment_centre;
656  if (fChargeWeighted)
657  segment_centre =
658  IShowerTool::GetLArPandoraShowerAlg().ShowerCentre(clockData, detProp, segment, fmh);
659  else
660  segment_centre = IShowerTool::GetLArPandoraShowerAlg().ShowerCentre(segment);
661 
662  double residual = CalculateResidual(segment, primary_axis, segment_centre);
663 
664  return residual;
665  }
666 
667  double
669  const detinfo::DetectorClocksData& clockData,
671  std::vector<art::Ptr<recob::SpacePoint>>& segment,
672  const art::FindManyP<recob::Hit>& fmh,
673  int& max_residual_point)
674  {
675 
676  TVector3 primary_axis;
677  if (fChargeWeighted)
678  primary_axis = ShowerPCAVector(clockData, detProp, segment, fmh);
679  else
680  primary_axis = ShowerPCAVector(segment);
681 
682  TVector3 segment_centre;
683  if (fChargeWeighted)
684  segment_centre =
685  IShowerTool::GetLArPandoraShowerAlg().ShowerCentre(clockData, detProp, segment, fmh);
686  else
687  segment_centre = IShowerTool::GetLArPandoraShowerAlg().ShowerCentre(segment);
688 
689  double residual = CalculateResidual(segment, primary_axis, segment_centre, max_residual_point);
690 
691  return residual;
692  }
693 
694  bool
696  const detinfo::DetectorClocksData& clockData,
698  std::vector<art::Ptr<recob::SpacePoint>>& segment,
699  std::vector<art::Ptr<recob::SpacePoint>>& reduced_sps_pool,
700  const art::FindManyP<recob::Hit>& fmh,
701  double current_residual)
702  {
703 
704  bool ok = true;
705  //If the pool is empty, then there is nothing to do (sad)
706  if (reduced_sps_pool.empty()) return !ok;
707  //Drop the last space point
708  segment.pop_back();
709  //Add one point
710  AddSpacePointsToSegment(segment, reduced_sps_pool, 1);
711  double residual = FitSegmentAndCalculateResidual(clockData, detProp, segment, fmh);
712 
713  ok = IsResidualOK(residual, current_residual, segment.size());
714  // std::cout<<"recursive refit: isok " << ok << " res: " << residual << " curr res: " << current_residual << std::endl;
715  if (ok) return ok;
717  clockData, detProp, segment, reduced_sps_pool, fmh, current_residual);
718  }
719 
720  double
722  TVector3& PCAEigenvector,
723  TVector3& TrackPosition)
724  {
725 
726  double Residual = 0;
727 
728  for (auto const& sp : sps) {
729 
730  //Get the relative position of the spacepoint
731  TVector3 pos = IShowerTool::GetLArPandoraShowerAlg().SpacePointPosition(sp) - TrackPosition;
732 
733  //Gen the perpendicular distance
734  double len = pos.Dot(PCAEigenvector);
735  double perp = (pos - len * PCAEigenvector).Mag();
736 
737  Residual += perp;
738  }
739  return Residual;
740  }
741 
742  double
744  TVector3& PCAEigenvector,
745  TVector3& TrackPosition,
746  int& max_residual_point)
747  {
748 
749  double Residual = 0;
750  double max_residual = -999;
751 
752  for (auto const& sp : sps) {
753 
754  //Get the relative position of the spacepoint
755  TVector3 pos = IShowerTool::GetLArPandoraShowerAlg().SpacePointPosition(sp) - TrackPosition;
756 
757  //Gen the perpendicular distance
758  double len = pos.Dot(PCAEigenvector);
759  double perp = (pos - len * PCAEigenvector).Mag();
760 
761  Residual += perp;
762 
763  if (perp > max_residual) {
764  max_residual = perp;
765  max_residual_point = sp.key();
766  }
767  }
768  return Residual;
769  }
770 
771  std::vector<art::Ptr<recob::SpacePoint>>
773  TVector3 start_direction)
774  {
775  std::vector<art::Ptr<recob::SpacePoint>> fake_sps;
776  std::vector<art::Ptr<recob::SpacePoint>> segment_a =
777  CreateFakeSPLine(start_position, start_direction, 20);
778  fake_sps.insert(std::end(fake_sps), std::begin(segment_a), std::end(segment_a));
779 
780  //make a new segment:
781  TVector3 sp_position =
783  TVector3 direction = start_direction;
784  direction.RotateX(10. * 3.142 / 180.);
785  std::vector<art::Ptr<recob::SpacePoint>> segment_b =
786  CreateFakeSPLine(sp_position, direction, 10);
787  fake_sps.insert(std::end(fake_sps), std::begin(segment_b), std::end(segment_b));
788 
789  //Now make three branches that come from the end of the segment
790  TVector3 branching_position =
792 
793  TVector3 direction_branch_a = direction;
794  direction_branch_a.RotateZ(15. * 3.142 / 180.);
795  std::vector<art::Ptr<recob::SpacePoint>> branch_a =
796  CreateFakeSPLine(branching_position, direction_branch_a, 6);
797  fake_sps.insert(std::end(fake_sps), std::begin(branch_a), std::end(branch_a));
798 
799  TVector3 direction_branch_b = direction;
800  direction_branch_b.RotateY(20. * 3.142 / 180.);
801  std::vector<art::Ptr<recob::SpacePoint>> branch_b =
802  CreateFakeSPLine(branching_position, direction_branch_b, 10);
803  fake_sps.insert(std::end(fake_sps), std::begin(branch_b), std::end(branch_b));
804 
805  TVector3 direction_branch_c = direction;
806  direction_branch_c.RotateX(3. * 3.142 / 180.);
807  std::vector<art::Ptr<recob::SpacePoint>> branch_c =
808  CreateFakeSPLine(branching_position, direction_branch_c, 20);
809  fake_sps.insert(std::end(fake_sps), std::begin(branch_c), std::end(branch_c));
810 
811  return fake_sps;
812  }
813 
814  std::vector<art::Ptr<recob::SpacePoint>>
816  TVector3 start_direction,
817  int npoints)
818  {
819  std::vector<art::Ptr<recob::SpacePoint>> fake_sps;
820  art::ProductID prod_id(std::string("totally_genuine"));
821  size_t current_id = 500000;
822 
823  double step_length = 0.2;
824  for (double i_point = 0; i_point < npoints; i_point++) {
825  TVector3 new_position = start_position + i_point * step_length * start_direction;
826  Double32_t xyz[3] = {new_position.X(), new_position.Y(), new_position.Z()};
827  Double32_t err[3] = {0., 0., 0.};
828  recob::SpacePoint* sp = new recob::SpacePoint(xyz, err, 0, 1);
829  fake_sps.emplace_back(art::Ptr<recob::SpacePoint>(prod_id, sp, current_id++));
830  }
831  return fake_sps;
832  }
833 
834  void
836  const art::Event& Event,
837  const art::FindManyP<recob::Hit>& dud_fmh)
838  {
839  TVector3 start_position(50, 50, 50);
840  TVector3 start_direction(0, 0, 1);
841  std::vector<art::Ptr<recob::SpacePoint>> fake_sps =
842  CreateFakeShowerTrajectory(start_position, start_direction);
843 
845 
846  std::vector<art::Ptr<recob::SpacePoint>> track_sps =
847  RunIncrementalSpacePointFinder(Event, fake_sps, dud_fmh);
848 
849  TGraph2D graph_sps;
850  for (size_t i_sp = 0; i_sp < fake_sps.size(); i_sp++) {
851  graph_sps.SetPoint(graph_sps.GetN(),
852  fake_sps[i_sp]->XYZ()[0],
853  fake_sps[i_sp]->XYZ()[1],
854  fake_sps[i_sp]->XYZ()[2]);
855  }
856  TGraph2D graph_track_sps;
857  for (size_t i_sp = 0; i_sp < track_sps.size(); i_sp++) {
858  graph_track_sps.SetPoint(graph_track_sps.GetN(),
859  track_sps[i_sp]->XYZ()[0],
860  track_sps[i_sp]->XYZ()[1],
861  track_sps[i_sp]->XYZ()[2]);
862  }
863 
864  art::ServiceHandle<art::TFileService> tfs;
865 
866  TCanvas* canvas = tfs->make<TCanvas>("test_inc_can", "test_inc_can");
867  canvas->SetName("test_inc_can");
868  graph_sps.SetMarkerStyle(8);
869  graph_sps.SetMarkerColor(1);
870  graph_sps.SetFillColor(1);
871  graph_sps.Draw("p");
872 
873  graph_track_sps.SetMarkerStyle(8);
874  graph_track_sps.SetMarkerColor(2);
875  graph_track_sps.SetFillColor(2);
876  graph_track_sps.Draw("samep");
877  canvas->Write();
878 
879  fRunTest = false;
880  return;
881  }
882 }
883 
double FitSegmentAndCalculateResidual(const detinfo::DetectorClocksData &clockData, const detinfo::DetectorPropertiesData &detProp, std::vector< art::Ptr< recob::SpacePoint >> &segment, const art::FindManyP< recob::Hit > &fmh)
double std(const std::vector< short > &wf, const double ped_mean, size_t start, size_t nsample)
Definition: UtilFunc.cxx:42
double DistanceBetweenSpacePoints(art::Ptr< recob::SpacePoint > const &sp_a, art::Ptr< recob::SpacePoint > const &sp_b) const
std::vector< art::Ptr< recob::SpacePoint > > RunIncrementalSpacePointFinder(const art::Event &Event, std::vector< art::Ptr< recob::SpacePoint >> const &sps, const art::FindManyP< recob::Hit > &fmh)
bool IsResidualOK(double new_residual, double current_residual)
void OrderShowerSpacePoints(std::vector< art::Ptr< recob::SpacePoint >> &showersps, TVector3 const &vertex, TVector3 const &direction) const
double CalculateResidual(std::vector< art::Ptr< recob::SpacePoint >> &sps, TVector3 &PCAEigenvector, TVector3 &TrackPosition)
Declaration of signal hit object.
EResult err(const char *call)
void SetElement(T &dataproduct, const std::string &Name, bool checktag=false)
static constexpr bool
const art::FindManyP< T1 > & GetFindManyP(const art::ValidHandle< std::vector< T2 > > &handle, const art::Event &evt, const art::InputTag &moduleTag)
bool RecursivelyReplaceLastSpacePointAndRefit(const detinfo::DetectorClocksData &clockData, const detinfo::DetectorPropertiesData &detProp, std::vector< art::Ptr< recob::SpacePoint >> &segment, std::vector< art::Ptr< recob::SpacePoint >> &reduced_sps_pool, const art::FindManyP< recob::Hit > &fmh, double current_residual)
process_name hit
Definition: cheaterreco.fcl:51
TVector3 ShowerPCAVector(std::vector< art::Ptr< recob::SpacePoint >> &sps)
double SpacePointTime(art::Ptr< recob::SpacePoint > const &sp, art::FindManyP< recob::Hit > const &fmh) const
void PruneTrack(std::vector< art::Ptr< recob::SpacePoint >> &initial_track)
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
double distance(geo::Point_t const &point, CathodeDesc_t const &cathode)
Returns the distance of a point from the cathode.
void RunTestOfIncrementalSpacePointFinder(const art::Event &Event, const art::FindManyP< recob::Hit > &dud_fmh)
int CalculateElement(const art::Ptr< recob::PFParticle > &pfparticle, art::Event &Event, reco::shower::ShowerElementHolder &ShowerEleHolder) override
bool IsResidualOK(double new_residual, double current_residual, size_t no_sps)
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
bool CheckElement(const std::string &Name) const
double SpacePointProjection(art::Ptr< recob::SpacePoint > const &sp, TVector3 const &vertex, TVector3 const &direction) const
int GetElement(const std::string &Name, T &Element) const
void PruneFrontOfSPSPool(std::vector< art::Ptr< recob::SpacePoint >> &sps_pool, std::vector< art::Ptr< recob::SpacePoint >> const &initial_track)
const shower::LArPandoraShowerAlg & GetLArPandoraShowerAlg() const
Definition: IShowerTool.h:88
auto begin(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:573
double SpacePointCharge(art::Ptr< recob::SpacePoint > const &sp, art::FindManyP< recob::Hit > const &fmh) const
void MakeTrackSeed(const detinfo::DetectorClocksData &clockData, const detinfo::DetectorPropertiesData &detProp, std::vector< art::Ptr< recob::SpacePoint >> &segment, const art::FindManyP< recob::Hit > &fmh)
bool IsSegmentValid(std::vector< art::Ptr< recob::SpacePoint >> const &segment)
Contains all timing reference information for the detector.
constexpr double dist(const TReal *x, const TReal *y, const unsigned int dimension)
std::vector< art::Ptr< recob::SpacePoint > > CreateFakeSPLine(TVector3 start_position, TVector3 start_direction, int npoints)
TVector3 ShowerCentre(std::vector< art::Ptr< recob::SpacePoint >> const &showersps) const
bool IncrementallyFitSegment(const detinfo::DetectorClocksData &clockData, const detinfo::DetectorPropertiesData &detProp, std::vector< art::Ptr< recob::SpacePoint >> &segment, std::vector< art::Ptr< recob::SpacePoint >> &sps_pool, const art::FindManyP< recob::Hit > &fmh, double current_residual)
2D representation of charge deposited in the TDC/wire plane
Definition: Hit.h:48
art::ServiceHandle< art::TFileService > tfs
std::vector< art::Ptr< recob::SpacePoint > > CreateFakeShowerTrajectory(TVector3 start_position, TVector3 start_direction)
void AddSpacePointsToSegment(std::vector< art::Ptr< recob::SpacePoint >> &segment, std::vector< art::Ptr< recob::SpacePoint >> &sps_pool, size_t num_sps_to_take)
double sampling_rate(DetectorClocksData const &data)
Returns the period of the TPC readout electronics clock.
auto const detProp
TVector3 SpacePointPosition(art::Ptr< recob::SpacePoint > const &sp) const