LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
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
11 
12 //LArSoft Includes
20 
21 //Root Includes
22 #include "Math/RotationX.h"
23 #include "Math/RotationY.h"
24 #include "Math/RotationZ.h"
25 #include "TCanvas.h"
26 #include "TGraph2D.h"
27 #include "TPrincipal.h"
28 
29 namespace ShowerRecoTools {
30 
32 
33  public:
35 
36  //Generic Direction Finder
37  int CalculateElement(const art::Ptr<recob::PFParticle>& pfparticle,
38  art::Event& Event,
39  reco::shower::ShowerElementHolder& ShowerEleHolder) override;
40 
41  private:
42  std::vector<art::Ptr<recob::SpacePoint>> RunIncrementalSpacePointFinder(
43  const art::Event& Event,
45  const art::FindManyP<recob::Hit>& fmh);
46 
48  std::vector<art::Ptr<recob::SpacePoint>> const& initial_track);
49 
51 
54  size_t num_sps_to_take);
55 
57 
59  const detinfo::DetectorPropertiesData& detProp,
62  const art::FindManyP<recob::Hit>& fmh,
63  double current_residual);
64 
66  const detinfo::DetectorPropertiesData& detProp,
68  const art::FindManyP<recob::Hit>& fmh);
69 
71  const detinfo::DetectorPropertiesData& detProp,
73  const art::FindManyP<recob::Hit>& fmh,
74  int& max_residual_point);
75 
77  const detinfo::DetectorClocksData& clockData,
78  const detinfo::DetectorPropertiesData& detProp,
80  std::vector<art::Ptr<recob::SpacePoint>>& reduced_sps_pool,
81  const art::FindManyP<recob::Hit>& fmh,
82  double current_residual);
83 
84  bool IsResidualOK(double new_residual, double current_residual) const
85  {
86  return new_residual - current_residual < fMaxResidualDiff;
87  }
88  bool IsResidualOK(double residual, size_t no_sps) const
89  {
90  return residual / no_sps < fMaxAverageResidual;
91  }
92  bool IsResidualOK(double new_residual, double current_residual, size_t no_sps) const
93  {
94  return IsResidualOK(new_residual, current_residual) && IsResidualOK(new_residual, no_sps);
95  }
96 
98  geo::Vector_t const& PCAEigenvector,
99  geo::Point_t const& TrackPosition) const;
100 
102  geo::Vector_t const& PCAEigenvector,
103  geo::Point_t const& TrackPosition,
104  int& max_residual_point) const;
105 
106  //Function to calculate the shower direction using a charge weight 3D PCA calculation.
108 
110  const detinfo::DetectorPropertiesData& detProp,
112  const art::FindManyP<recob::Hit>& fmh) const;
113 
114  std::vector<art::Ptr<recob::SpacePoint>> CreateFakeShowerTrajectory(
115  geo::Point_t const& start_position,
116  geo::Vector_t const& start_direction);
117  std::vector<art::Ptr<recob::SpacePoint>> CreateFakeSPLine(geo::Point_t const& start_position,
118  geo::Vector_t const& start_direction,
119  int npoints);
121  const art::FindManyP<recob::Hit>& dud_fmh);
122 
123  void MakeTrackSeed(const detinfo::DetectorClocksData& clockData,
124  const detinfo::DetectorPropertiesData& detProp,
126  const art::FindManyP<recob::Hit>& fmh);
127 
128  //Services
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"))
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 
181  const art::Ptr<recob::PFParticle>& pfparticle,
182  art::Event& Event,
183  reco::shower::ShowerElementHolder& ShowerEleHolder)
184  {
185 
186  //This is all based on the shower vertex being known. If it is not lets not do the track
187  if (!ShowerEleHolder.CheckElement(fShowerStartPositionInputLabel)) {
188  if (fVerbose)
189  mf::LogError("ShowerIncrementalTrackHitFinder")
190  << "Start position not set, returning " << std::endl;
191  return 1;
192  }
193 
194  // Get the assocated pfParicle Handle
195  auto const pfpHandle = Event.getValidHandle<std::vector<recob::PFParticle>>(fPFParticleLabel);
196 
197  // Get the spacepoint - PFParticle assn
198  const art::FindManyP<recob::SpacePoint>& fmspp =
199  ShowerEleHolder.GetFindManyP<recob::SpacePoint>(pfpHandle, Event, fPFParticleLabel);
200 
201  // Get the spacepoints
202  auto const spHandle = Event.getValidHandle<std::vector<recob::SpacePoint>>(fPFParticleLabel);
203 
204  // Get the hits associated with the space points
205  const art::FindManyP<recob::Hit>& fmh =
206  ShowerEleHolder.GetFindManyP<recob::Hit>(spHandle, Event, fPFParticleLabel);
207 
208  // Get the SpacePoints
209  std::vector<art::Ptr<recob::SpacePoint>> spacePoints = fmspp.at(pfparticle.key());
210 
211  //We cannot progress with no spacepoints.
212  if (spacePoints.empty()) {
213  if (fVerbose)
214  mf::LogError("ShowerIncrementalTrackHitFinder")
215  << "No space points, returning " << std::endl;
216  return 1;
217  }
218 
219  geo::Point_t ShowerStartPosition = {-999, -999, -999};
220  ShowerEleHolder.GetElement(fShowerStartPositionInputLabel, ShowerStartPosition);
221 
222  //Decide if the you want to use the direction of the shower or make one.
223  if (fUseShowerDirection) {
224 
225  if (!ShowerEleHolder.CheckElement(fShowerDirectionInputLabel)) {
226  if (fVerbose)
227  mf::LogError("ShowerIncrementalTrackHitFinder")
228  << "Direction not set, returning " << std::endl;
229  return 1;
230  }
231 
232  geo::Vector_t ShowerDirection = {-999, -999, -999};
233  ShowerEleHolder.GetElement(fShowerDirectionInputLabel, ShowerDirection);
234 
235  //Order the spacepoints
237  spacePoints, ShowerStartPosition, ShowerDirection);
238  //Remove the back hits if requird.
239  if (fForwardHitsOnly) {
240  int back_sps = 0;
241  for (auto spacePoint : spacePoints) {
243  spacePoint, ShowerStartPosition, ShowerDirection);
244  if (proj < 0) { ++back_sps; }
245  if (proj > 0) { break; }
246  }
247  spacePoints.erase(spacePoints.begin(), spacePoints.begin() + back_sps);
248  }
249  }
250  else {
251  //Order the spacepoint using the magnitude away from the vertex
253  ShowerStartPosition);
254  }
255 
256  //Remove the first x spacepoints
257  int frontsp = 0;
258  for (auto const& spacePoint : spacePoints) {
259  double dist = (spacePoint->position() - ShowerStartPosition).R();
260  if (dist > fStartDistanceCut) { break; }
261  ++frontsp;
262  }
263  spacePoints.erase(spacePoints.begin(), spacePoints.begin() + frontsp);
264 
265  //Bin anything above x cm
266  int sp_iter = 0;
267  for (auto const& spacePoint : spacePoints) {
268  double dist = (spacePoint->position() - ShowerStartPosition).R();
269  if (dist > fDistanceCut) { break; }
270  ++sp_iter;
271  }
272  spacePoints.erase(spacePoints.begin() + sp_iter, spacePoints.end());
273 
274  if (spacePoints.size() < 3) {
275  if (fVerbose)
276  mf::LogError("ShowerIncrementalTrackHitFinder")
277  << "Not enough spacepoints bailing" << std::endl;
278  return 1;
279  }
280 
281  //Create fake hits and test the algorithm
283 
284  //Actually runt he algorithm.
285  std::vector<art::Ptr<recob::SpacePoint>> track_sps =
286  RunIncrementalSpacePointFinder(Event, spacePoints, fmh);
287 
288  // Get the hits associated to the space points and seperate them by planes
289  std::vector<art::Ptr<recob::Hit>> trackHits;
290  for (auto const& spacePoint : track_sps) {
291  std::vector<art::Ptr<recob::Hit>> hits = fmh.at(spacePoint.key());
292  for (auto const& hit : hits) {
293  trackHits.push_back(hit);
294  }
295  }
296 
297  //Add to the holder
298  ShowerEleHolder.SetElement(trackHits, fInitialTrackHitsOutputLabel);
299  ShowerEleHolder.SetElement(track_sps, fInitialTrackSpacePointsOutputLabel);
300 
301  return 0;
302  }
303 
305  std::vector<art::Ptr<recob::SpacePoint>> const& sps) const
306  {
307  //Initialise the the PCA.
308  TPrincipal pca(3, "");
309 
310  //Normalise the spacepoints, charge weight and add to the PCA.
311  for (auto& sp : sps) {
312  auto const sp_position = sp->position();
313  double sp_coord[3] = {sp_position.X(), sp_position.Y(), sp_position.Z()};
314  pca.AddRow(sp_coord);
315  }
316 
317  //Evaluate the PCA
318  pca.MakePrincipals();
319 
320  //Get the Eigenvectors.
321  const TMatrixD* Eigenvectors = pca.GetEigenVectors();
322 
323  return {(*Eigenvectors)[0][0], (*Eigenvectors)[1][0], (*Eigenvectors)[2][0]};
324  }
325 
326  //Function to calculate the shower direction using a charge weight 3D PCA calculation.
328  const detinfo::DetectorClocksData& clockData,
329  const detinfo::DetectorPropertiesData& detProp,
331  const art::FindManyP<recob::Hit>& fmh) const
332  {
333  TPrincipal pca(3, "");
334 
335  float TotalCharge = 0;
336 
337  //Normalise the spacepoints, charge weight and add to the PCA.
338  for (auto& sp : sps) {
339  auto const sp_position = sp->position();
340 
341  float wht = 1;
342 
343  if (fChargeWeighted) {
344  float Charge = IShowerTool::GetLArPandoraShowerAlg().SpacePointCharge(sp, fmh);
345  float Time = IShowerTool::GetLArPandoraShowerAlg().SpacePointTime(sp, fmh);
346 
347  //Correct for the lifetime at the moment.
348  Charge *= std::exp((sampling_rate(clockData) * Time) / (detProp.ElectronLifetime() * 1e3));
349 
350  //Charge Weight
351  wht *= std::sqrt(Charge / TotalCharge);
352  }
353 
354  double sp_coord[3] = {sp_position.X() * wht, sp_position.Y() * wht, sp_position.Z() * wht};
355  pca.AddRow(sp_coord);
356  }
357 
358  //Evaluate the PCA
359  pca.MakePrincipals();
360 
361  //Get the Eigenvectors.
362  const TMatrixD* Eigenvectors = pca.GetEigenVectors();
363 
364  return {(*Eigenvectors)[0][0], (*Eigenvectors)[1][0], (*Eigenvectors)[2][0]};
365  }
366 
367  //Function to remove the spacepoint with the highest residual until we have a track which matches the
368  //residual criteria.
370  const detinfo::DetectorClocksData& clockData,
371  const detinfo::DetectorPropertiesData& detProp,
373  const art::FindManyP<recob::Hit>& fmh)
374  {
375 
376  bool ok = true;
377 
378  int maxresidual_point = 0;
379 
380  //Check the residual
381  double residual =
382  FitSegmentAndCalculateResidual(clockData, detProp, segment, fmh, maxresidual_point);
383 
384  //Is it okay
385  ok = IsResidualOK(residual, segment.size());
386 
387  //Remove points until we can fit a track.
388  while (!ok && segment.size() != 1) {
389 
390  //Remove the point with the highest residual
391  for (auto sp = segment.begin(); sp != segment.end(); ++sp) {
392  if (sp->key() == (unsigned)maxresidual_point) {
393  segment.erase(sp);
394  break;
395  }
396  }
397 
398  //Check the residual
399  double residual =
400  FitSegmentAndCalculateResidual(clockData, detProp, segment, fmh, maxresidual_point);
401 
402  //Is it okay
403  ok = IsResidualOK(residual, segment.size());
404  }
405  }
406 
407  std::vector<art::Ptr<recob::SpacePoint>>
409  const art::Event& Event,
411  const art::FindManyP<recob::Hit>& fmh)
412  {
413 
414  auto const clockData =
416  auto const detProp =
418 
419  //Create space point pool (yes we are copying the input vector because we're going to twiddle with it
420  std::vector<art::Ptr<recob::SpacePoint>> sps_pool = sps;
421  std::vector<art::Ptr<recob::SpacePoint>> initial_track;
422  std::vector<art::Ptr<recob::SpacePoint>> track_segment_copy;
423 
424  while (sps_pool.size() > 0) {
425  //PruneFrontOfSPSPool(sps_pool, initial_track);
426 
427  std::vector<art::Ptr<recob::SpacePoint>> track_segment;
428  AddSpacePointsToSegment(track_segment, sps_pool, (size_t)(fStartFitSize));
429  if (!IsSegmentValid(track_segment)) {
430  //Clear the pool and lets leave this place
431  sps_pool.clear();
432  break;
433  }
434 
435  //Lets really try to make the initial track seed.
436  if (fMakeTrackSeed && sps_pool.size() + fStartFitSize == sps.size()) {
437  MakeTrackSeed(clockData, detProp, track_segment, fmh);
438  if (track_segment.empty()) break;
439 
440  track_segment_copy = track_segment;
441  }
442 
443  //A sleight of hand coming up. We are going to move the last sp from the segment back into the pool so
444  //that it makes kick starting the recursion easier (sneaky)
445  //TODO defend against segments that are too small for this to work (I dunno who is running the alg with
446  //fStartFitMinSize==0 but whatever
447  sps_pool.insert(sps_pool.begin(), track_segment.back());
448  track_segment.pop_back();
449  double current_residual = 0;
450  size_t initial_segment_size = track_segment.size();
451 
452  IncrementallyFitSegment(clockData, detProp, track_segment, sps_pool, fmh, current_residual);
453 
454  //Check if the track has grown in size at all
455  if (initial_segment_size == track_segment.size()) {
456  //The incremental fitter could not grow th track at all. SAD!
457  //Clear the pool and let's get out of here
458  sps_pool.clear();
459  break;
460  }
461  else {
462  //We did some good fitting and everyone is really happy with it
463  //Let's store all of the hits in the final space point vector
464  AddSpacePointsToSegment(initial_track, track_segment, track_segment.size());
465  }
466  }
467 
468  //If we have failed then no worry we have the seed. We shall just give those points.
469  if (fMakeTrackSeed && initial_track.empty()) initial_track = track_segment_copy;
470 
471  //Runt the algorithm that attepmts to remove hits too far away from the track.
472  PruneTrack(initial_track);
473 
474  return initial_track;
475  }
476 
479  std::vector<art::Ptr<recob::SpacePoint>> const& initial_track)
480  {
481 
482  //If the initial track is empty then there is no pruning to do
483  if (initial_track.empty()) return;
485  initial_track.back(), sps_pool.front());
486  while (distance > 1 && sps_pool.size() > 0) {
487  sps_pool.erase(sps_pool.begin());
489  initial_track.back(), sps_pool.front());
490  }
491  return;
492  }
493 
496  {
497 
498  if (initial_track.empty()) return;
499  std::vector<art::Ptr<recob::SpacePoint>>::iterator sps_it = initial_track.begin();
500  while (sps_it != std::next(initial_track.end(), -1)) {
501  std::vector<art::Ptr<recob::SpacePoint>>::iterator next_sps_it = std::next(sps_it, 1);
502  double distance =
504  if (distance > fTrackMaxAdjacentSPDistance) { initial_track.erase(next_sps_it); }
505  else {
506  sps_it++;
507  }
508  }
509  return;
510  }
511 
515  size_t num_sps_to_take)
516  {
517  size_t new_segment_size = segment.size() + num_sps_to_take;
518  while (segment.size() < new_segment_size && sps_pool.size() > 0) {
519  segment.push_back(sps_pool[0]);
520  sps_pool.erase(sps_pool.begin());
521  }
522  return;
523  }
524 
527  {
528  bool ok = true;
529  if (segment.size() < (size_t)(fStartFitSize)) return !ok;
530 
531  return ok;
532  }
533 
535  const detinfo::DetectorClocksData& clockData,
536  const detinfo::DetectorPropertiesData& detProp,
539  const art::FindManyP<recob::Hit>& fmh,
540  double current_residual)
541  {
542 
543  bool ok = true;
544  //Firstly, are there any space points left???
545  if (sps_pool.empty()) return !ok;
546  //Fit the current line
547  current_residual = FitSegmentAndCalculateResidual(clockData, detProp, segment, fmh);
548  //Take a space point from the pool and plonk it onto the seggieweggie
549  AddSpacePointsToSegment(segment, sps_pool, 1);
550  //Fit again
551  double residual = FitSegmentAndCalculateResidual(clockData, detProp, segment, fmh);
552 
553  ok = IsResidualOK(residual, current_residual, segment.size());
554  if (!ok) {
555  //Create a sub pool of space points to pass to the refitter
556  std::vector<art::Ptr<recob::SpacePoint>> sub_sps_pool;
557  AddSpacePointsToSegment(sub_sps_pool, sps_pool, fNMissPoints);
558  //We'll need an additional copy of this pool, as we will need the space points if we have to start a new
559  //segment later, but all of the funtionality drains the pools during use
560  std::vector<art::Ptr<recob::SpacePoint>> sub_sps_pool_cache = sub_sps_pool;
561  //The most recently added SP to the segment is bad but it will get thrown away by RecursivelyReplaceLastSpacePointAndRefit
562  //It's possible that we will need it if we end up forming an entirely new line from scratch, so
563  //add the bad SP to the front of the cache
564  sub_sps_pool_cache.insert(sub_sps_pool_cache.begin(), segment.back());
566  clockData, detProp, segment, sub_sps_pool, fmh, current_residual);
567  if (ok) {
568  //The refitting may have dropped a couple of points but it managed to find a point that kept the residual
569  //at a sensible value.
570  //Add the remaining SPS in the reduced pool back t othe start of the larger pool
571  while (sub_sps_pool.size() > 0) {
572  sps_pool.insert(sps_pool.begin(), sub_sps_pool.back());
573  sub_sps_pool.pop_back();
574  }
575  //We'll need the latest residual now that we've managed to refit the track
576  residual = FitSegmentAndCalculateResidual(clockData, detProp, segment, fmh);
577  }
578  else {
579  //All of the space points in the reduced pool could not sensibly refit the track. The reduced pool will be
580  //empty so move all of the cached space points back into the main pool
581  // std::cout<<"The refitting was NOT a success, dumping all " << sub_sps_pool_cache.size() << " sps back into the pool" << std::endl;
582  while (sub_sps_pool_cache.size() > 0) {
583  sps_pool.insert(sps_pool.begin(), sub_sps_pool_cache.back());
584  sub_sps_pool_cache.pop_back();
585  }
586  //The bad point is still on the segment, so remove it
587  segment.pop_back();
588  return !ok;
589  }
590  }
591 
592  //Update the residual
593  current_residual = residual;
594 
595  //Round and round we go
596  //NOBODY GETS OFF MR BONES WILD RIDE
597  return IncrementallyFitSegment(clockData, detProp, segment, sps_pool, fmh, current_residual);
598  }
599 
601  const detinfo::DetectorClocksData& clockData,
602  const detinfo::DetectorPropertiesData& detProp,
604  const art::FindManyP<recob::Hit>& fmh)
605  {
606  geo::Vector_t primary_axis;
607  if (fChargeWeighted)
608  primary_axis = ShowerPCAVector(clockData, detProp, segment, fmh);
609  else
610  primary_axis = ShowerPCAVector(segment);
611 
612  geo::Point_t segment_centre;
613  if (fChargeWeighted)
614  segment_centre =
615  IShowerTool::GetLArPandoraShowerAlg().ShowerCentre(clockData, detProp, segment, fmh);
616  else
617  segment_centre = IShowerTool::GetLArPandoraShowerAlg().ShowerCentre(segment);
618 
619  return CalculateResidual(segment, primary_axis, segment_centre);
620  }
621 
623  const detinfo::DetectorClocksData& clockData,
624  const detinfo::DetectorPropertiesData& detProp,
626  const art::FindManyP<recob::Hit>& fmh,
627  int& max_residual_point)
628  {
629  geo::Vector_t primary_axis;
630  if (fChargeWeighted)
631  primary_axis = ShowerPCAVector(clockData, detProp, segment, fmh);
632  else
633  primary_axis = ShowerPCAVector(segment);
634 
635  geo::Point_t segment_centre;
636  if (fChargeWeighted)
637  segment_centre =
638  IShowerTool::GetLArPandoraShowerAlg().ShowerCentre(clockData, detProp, segment, fmh);
639  else
640  segment_centre = IShowerTool::GetLArPandoraShowerAlg().ShowerCentre(segment);
641 
642  return CalculateResidual(segment, primary_axis, segment_centre, max_residual_point);
643  }
644 
646  const detinfo::DetectorClocksData& clockData,
647  const detinfo::DetectorPropertiesData& detProp,
649  std::vector<art::Ptr<recob::SpacePoint>>& reduced_sps_pool,
650  const art::FindManyP<recob::Hit>& fmh,
651  double current_residual)
652  {
653 
654  bool ok = true;
655  //If the pool is empty, then there is nothing to do (sad)
656  if (reduced_sps_pool.empty()) return !ok;
657  //Drop the last space point
658  segment.pop_back();
659  //Add one point
660  AddSpacePointsToSegment(segment, reduced_sps_pool, 1);
661  double residual = FitSegmentAndCalculateResidual(clockData, detProp, segment, fmh);
662 
663  ok = IsResidualOK(residual, current_residual, segment.size());
664  // std::cout<<"recursive refit: isok " << ok << " res: " << residual << " curr res: " << current_residual << std::endl;
665  if (ok) return ok;
667  clockData, detProp, segment, reduced_sps_pool, fmh, current_residual);
668  }
669 
672  geo::Vector_t const& PCAEigenvector,
673  geo::Point_t const& TrackPosition) const
674  {
675  double Residual = 0;
676 
677  for (auto const& sp : sps) {
678 
679  //Get the relative position of the spacepoint
680  auto const pos = sp->position() - TrackPosition;
681 
682  //Gen the perpendicular distance
683  double len = pos.Dot(PCAEigenvector);
684  double perp = (pos - len * PCAEigenvector).R();
685 
686  Residual += perp;
687  }
688  return Residual;
689  }
690 
693  geo::Vector_t const& PCAEigenvector,
694  geo::Point_t const& TrackPosition,
695  int& max_residual_point) const
696  {
697  double Residual = 0;
698  double max_residual = -999;
699 
700  for (auto const& sp : sps) {
701 
702  //Get the relative position of the spacepoint
703  auto const pos = sp->position() - TrackPosition;
704 
705  //Gen the perpendicular distance
706  double len = pos.Dot(PCAEigenvector);
707  double perp = (pos - len * PCAEigenvector).R();
708 
709  Residual += perp;
710 
711  if (perp > max_residual) {
712  max_residual = perp;
713  max_residual_point = sp.key();
714  }
715  }
716  return Residual;
717  }
718 
719  std::vector<art::Ptr<recob::SpacePoint>>
721  geo::Vector_t const& start_direction)
722  {
723  std::vector<art::Ptr<recob::SpacePoint>> fake_sps;
724  std::vector<art::Ptr<recob::SpacePoint>> segment_a =
725  CreateFakeSPLine(start_position, start_direction, 20);
726  fake_sps.insert(std::end(fake_sps), std::begin(segment_a), std::end(segment_a));
727 
728  //make a new segment:
729  auto const sp_position = fake_sps.back()->position();
730  auto const direction = ROOT::Math::RotationX{10. * 3.142 / 180.}(start_direction);
731  std::vector<art::Ptr<recob::SpacePoint>> segment_b =
732  CreateFakeSPLine(sp_position, direction, 10);
733  fake_sps.insert(std::end(fake_sps), std::begin(segment_b), std::end(segment_b));
734 
735  //Now make three branches that come from the end of the segment
736  auto const branching_position = fake_sps.back()->position();
737 
738  auto const direction_branch_a = ROOT::Math::RotationZ{15. * 3.142 / 180.}(direction);
739  std::vector<art::Ptr<recob::SpacePoint>> branch_a =
740  CreateFakeSPLine(branching_position, direction_branch_a, 6);
741  fake_sps.insert(std::end(fake_sps), std::begin(branch_a), std::end(branch_a));
742 
743  auto const direction_branch_b = ROOT::Math::RotationY{20. * 3.142 / 180.}(direction);
744  std::vector<art::Ptr<recob::SpacePoint>> branch_b =
745  CreateFakeSPLine(branching_position, direction_branch_b, 10);
746  fake_sps.insert(std::end(fake_sps), std::begin(branch_b), std::end(branch_b));
747 
748  auto const direction_branch_c = ROOT::Math::RotationX{3. * 3.142 / 180.}(direction);
749  std::vector<art::Ptr<recob::SpacePoint>> branch_c =
750  CreateFakeSPLine(branching_position, direction_branch_c, 20);
751  fake_sps.insert(std::end(fake_sps), std::begin(branch_c), std::end(branch_c));
752 
753  return fake_sps;
754  }
755 
756  std::vector<art::Ptr<recob::SpacePoint>> ShowerIncrementalTrackHitFinder::CreateFakeSPLine(
757  geo::Point_t const& start_position,
758  geo::Vector_t const& start_direction,
759  int npoints)
760  {
761  std::vector<art::Ptr<recob::SpacePoint>> fake_sps;
762  art::ProductID prod_id(std::string("totally_genuine"));
763  size_t current_id = 500000;
764 
765  double step_length = 0.2;
766  for (double i_point = 0; i_point < npoints; i_point++) {
767  auto const new_position = start_position + i_point * step_length * start_direction;
768  Double32_t xyz[3] = {new_position.X(), new_position.Y(), new_position.Z()};
769  Double32_t err[3] = {0., 0., 0.};
770  recob::SpacePoint* sp = new recob::SpacePoint(xyz, err, 0, 1);
771  fake_sps.emplace_back(art::Ptr<recob::SpacePoint>(prod_id, sp, current_id++));
772  }
773  return fake_sps;
774  }
775 
777  const art::Event& Event,
778  const art::FindManyP<recob::Hit>& dud_fmh)
779  {
780  geo::Point_t const start_position(50, 50, 50);
781  geo::Vector_t const start_direction(0, 0, 1);
782  std::vector<art::Ptr<recob::SpacePoint>> fake_sps =
783  CreateFakeShowerTrajectory(start_position, start_direction);
784 
786 
787  std::vector<art::Ptr<recob::SpacePoint>> track_sps =
788  RunIncrementalSpacePointFinder(Event, fake_sps, dud_fmh);
789 
790  TGraph2D graph_sps;
791  for (size_t i_sp = 0; i_sp < fake_sps.size(); i_sp++) {
792  graph_sps.SetPoint(graph_sps.GetN(),
793  fake_sps[i_sp]->XYZ()[0],
794  fake_sps[i_sp]->XYZ()[1],
795  fake_sps[i_sp]->XYZ()[2]);
796  }
797  TGraph2D graph_track_sps;
798  for (size_t i_sp = 0; i_sp < track_sps.size(); i_sp++) {
799  graph_track_sps.SetPoint(graph_track_sps.GetN(),
800  track_sps[i_sp]->XYZ()[0],
801  track_sps[i_sp]->XYZ()[1],
802  track_sps[i_sp]->XYZ()[2]);
803  }
804 
806 
807  TCanvas* canvas = tfs->make<TCanvas>("test_inc_can", "test_inc_can");
808  canvas->SetName("test_inc_can");
809  graph_sps.SetMarkerStyle(8);
810  graph_sps.SetMarkerColor(1);
811  graph_sps.SetFillColor(1);
812  graph_sps.Draw("p");
813 
814  graph_track_sps.SetMarkerStyle(8);
815  graph_track_sps.SetMarkerColor(2);
816  graph_track_sps.SetFillColor(2);
817  graph_track_sps.Draw("samep");
818  canvas->Write();
819 
820  fRunTest = false;
821  return;
822  }
823 }
824 
double FitSegmentAndCalculateResidual(const detinfo::DetectorClocksData &clockData, const detinfo::DetectorPropertiesData &detProp, std::vector< art::Ptr< recob::SpacePoint >> &segment, const art::FindManyP< recob::Hit > &fmh)
double DistanceBetweenSpacePoints(art::Ptr< recob::SpacePoint > const &sp_a, art::Ptr< recob::SpacePoint > const &sp_b) const
#define DEFINE_ART_CLASS_TOOL(tool)
Definition: ToolMacros.h:42
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space.
Definition: geo_vectors.h:160
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)
Declaration of signal hit object.
bool IsResidualOK(double new_residual, double current_residual, size_t no_sps) const
void SetElement(T &dataproduct, const std::string &Name, bool checktag=false)
STL namespace.
bool IsResidualOK(double new_residual, double current_residual) const
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)
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
geo::Vector_t ShowerPCAVector(std::vector< art::Ptr< recob::SpacePoint >> const &sps) const
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)
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:289
void hits()
Definition: readHits.C:15
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
parameter set interface
key_type key() const noexcept
Definition: Ptr.h:166
std::vector< art::Ptr< recob::SpacePoint > > CreateFakeSPLine(geo::Point_t const &start_position, geo::Vector_t const &start_direction, int npoints)
bool CheckElement(const std::string &Name) 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)
double SpacePointProjection(art::Ptr< recob::SpacePoint > const &sp, geo::Point_t const &vertex, geo::Vector_t const &direction) const
double CalculateResidual(std::vector< art::Ptr< recob::SpacePoint >> &sps, geo::Vector_t const &PCAEigenvector, geo::Point_t const &TrackPosition) const
Detector simulation of raw signals on wires.
const shower::LArPandoraShowerAlg & GetLArPandoraShowerAlg() const
Definition: IShowerTool.h:82
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)
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:180
bool IsSegmentValid(std::vector< art::Ptr< recob::SpacePoint >> const &segment)
ValidHandle< PROD > getValidHandle(InputTag const &tag) const
decltype(auto) get(T &&obj)
ADL-aware version of std::to_string.
Definition: StdUtils.h:120
Contains all timing reference information for the detector.
constexpr double dist(const TReal *x, const TReal *y, const unsigned int dimension)
geo::Point_t ShowerCentre(std::vector< art::Ptr< recob::SpacePoint >> const &showersps) const
void OrderShowerSpacePoints(std::vector< art::Ptr< recob::SpacePoint >> &showersps, geo::Point_t const &vertex, geo::Vector_t const &direction) const
Float_t proj
Definition: plot.C:35
Definition: MVAAlg.h:12
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)
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
Definition: StdUtils.h:69
std::vector< art::Ptr< recob::SpacePoint > > CreateFakeShowerTrajectory(geo::Point_t const &start_position, geo::Vector_t const &start_direction)
2D representation of charge deposited in the TDC/wire plane
Definition: Hit.h:46
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.
const art::FindManyP< T1 > & GetFindManyP(const art::ValidHandle< std::vector< T2 >> &handle, const art::Event &evt, const art::InputTag &moduleTag)
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33