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