Pandora
Pandora source code navigator
Loading...
Searching...
No Matches
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
13#include "lardata/DetectorInfoServices/DetectorClocksService.h"
14#include "lardata/DetectorInfoServices/DetectorPropertiesService.h"
15#include "lardataalg/DetectorInfo/DetectorPropertiesData.h"
16#include "lardataobj/RecoBase/Hit.h"
17#include "lardataobj/RecoBase/PFParticle.h"
18#include "lardataobj/RecoBase/SpacePoint.h"
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
29namespace ShowerRecoTools {
30
32
33 public:
34 ShowerIncrementalTrackHitFinder(const fhicl::ParameterSet& pset);
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,
44 std::vector<art::Ptr<recob::SpacePoint>> const& sps,
45 const art::FindManyP<recob::Hit>& fmh);
46
47 void PruneFrontOfSPSPool(std::vector<art::Ptr<recob::SpacePoint>>& sps_pool,
48 std::vector<art::Ptr<recob::SpacePoint>> const& initial_track);
49
50 void PruneTrack(std::vector<art::Ptr<recob::SpacePoint>>& initial_track);
51
52 void AddSpacePointsToSegment(std::vector<art::Ptr<recob::SpacePoint>>& segment,
53 std::vector<art::Ptr<recob::SpacePoint>>& sps_pool,
54 size_t num_sps_to_take);
55
56 bool IsSegmentValid(std::vector<art::Ptr<recob::SpacePoint>> const& segment);
57
58 bool IncrementallyFitSegment(const detinfo::DetectorClocksData& clockData,
59 const detinfo::DetectorPropertiesData& detProp,
60 std::vector<art::Ptr<recob::SpacePoint>>& segment,
61 std::vector<art::Ptr<recob::SpacePoint>>& sps_pool,
62 const art::FindManyP<recob::Hit>& fmh,
63 double current_residual);
64
65 double FitSegmentAndCalculateResidual(const detinfo::DetectorClocksData& clockData,
66 const detinfo::DetectorPropertiesData& detProp,
67 std::vector<art::Ptr<recob::SpacePoint>>& segment,
68 const art::FindManyP<recob::Hit>& fmh);
69
70 double FitSegmentAndCalculateResidual(const detinfo::DetectorClocksData& clockData,
71 const detinfo::DetectorPropertiesData& detProp,
72 std::vector<art::Ptr<recob::SpacePoint>>& segment,
73 const art::FindManyP<recob::Hit>& fmh,
74 int& max_residual_point);
75
77 const detinfo::DetectorClocksData& clockData,
78 const detinfo::DetectorPropertiesData& detProp,
79 std::vector<art::Ptr<recob::SpacePoint>>& segment,
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
97 double CalculateResidual(std::vector<art::Ptr<recob::SpacePoint>>& sps,
98 geo::Vector_t const& PCAEigenvector,
99 geo::Point_t const& TrackPosition) const;
100
101 double CalculateResidual(std::vector<art::Ptr<recob::SpacePoint>>& sps,
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.
107 geo::Vector_t ShowerPCAVector(std::vector<art::Ptr<recob::SpacePoint>> const& sps) const;
108
109 geo::Vector_t ShowerPCAVector(const detinfo::DetectorClocksData& clockData,
110 const detinfo::DetectorPropertiesData& detProp,
111 const std::vector<art::Ptr<recob::SpacePoint>>& sps,
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);
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;
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
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.
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,
330 const std::vector<art::Ptr<recob::SpacePoint>>& sps,
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) {
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,
372 std::vector<art::Ptr<recob::SpacePoint>>& segment,
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,
410 std::vector<art::Ptr<recob::SpacePoint>> const& sps,
411 const art::FindManyP<recob::Hit>& fmh)
412 {
413
414 auto const clockData =
415 art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(Event);
416 auto const detProp =
417 art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(Event, clockData);
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
478 std::vector<art::Ptr<recob::SpacePoint>>& sps_pool,
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
495 std::vector<art::Ptr<recob::SpacePoint>>& initial_track)
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
513 std::vector<art::Ptr<recob::SpacePoint>>& segment,
514 std::vector<art::Ptr<recob::SpacePoint>>& sps_pool,
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
526 std::vector<art::Ptr<recob::SpacePoint>> const& segment)
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,
537 std::vector<art::Ptr<recob::SpacePoint>>& segment,
538 std::vector<art::Ptr<recob::SpacePoint>>& sps_pool,
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,
603 std::vector<art::Ptr<recob::SpacePoint>>& segment,
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,
625 std::vector<art::Ptr<recob::SpacePoint>>& segment,
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,
648 std::vector<art::Ptr<recob::SpacePoint>>& segment,
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
671 std::vector<art::Ptr<recob::SpacePoint>>& sps,
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
692 std::vector<art::Ptr<recob::SpacePoint>>& sps,
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
805 art::ServiceHandle<art::TFileService> tfs;
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
const shower::LArPandoraShowerAlg & GetLArPandoraShowerAlg() const
Definition IShowerTool.h:82
int CalculateElement(const art::Ptr< recob::PFParticle > &pfparticle, art::Event &Event, reco::shower::ShowerElementHolder &ShowerEleHolder) override
std::vector< art::Ptr< recob::SpacePoint > > CreateFakeSPLine(geo::Point_t const &start_position, geo::Vector_t const &start_direction, int npoints)
void RunTestOfIncrementalSpacePointFinder(const art::Event &Event, const art::FindManyP< recob::Hit > &dud_fmh)
bool IsResidualOK(double new_residual, double current_residual, size_t no_sps) const
double CalculateResidual(std::vector< art::Ptr< recob::SpacePoint > > &sps, geo::Vector_t const &PCAEigenvector, geo::Point_t const &TrackPosition) 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)
void MakeTrackSeed(const detinfo::DetectorClocksData &clockData, const detinfo::DetectorPropertiesData &detProp, std::vector< art::Ptr< recob::SpacePoint > > &segment, const art::FindManyP< recob::Hit > &fmh)
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)
void PruneFrontOfSPSPool(std::vector< art::Ptr< recob::SpacePoint > > &sps_pool, std::vector< art::Ptr< recob::SpacePoint > > const &initial_track)
bool IsSegmentValid(std::vector< art::Ptr< recob::SpacePoint > > const &segment)
std::vector< art::Ptr< recob::SpacePoint > > CreateFakeShowerTrajectory(geo::Point_t const &start_position, geo::Vector_t const &start_direction)
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)
void PruneTrack(std::vector< art::Ptr< recob::SpacePoint > > &initial_track)
double FitSegmentAndCalculateResidual(const detinfo::DetectorClocksData &clockData, const detinfo::DetectorPropertiesData &detProp, std::vector< art::Ptr< recob::SpacePoint > > &segment, const art::FindManyP< recob::Hit > &fmh)
void AddSpacePointsToSegment(std::vector< art::Ptr< recob::SpacePoint > > &segment, std::vector< art::Ptr< recob::SpacePoint > > &sps_pool, size_t num_sps_to_take)
geo::Vector_t ShowerPCAVector(std::vector< art::Ptr< recob::SpacePoint > > const &sps) const
int GetElement(const std::string &Name, T &Element) const
const art::FindManyP< T1 > & GetFindManyP(const art::ValidHandle< std::vector< T2 > > &handle, const art::Event &evt, const art::InputTag &moduleTag)
void SetElement(T &dataproduct, const std::string &Name, bool checktag=false)
bool CheckElement(const std::string &Name) const
void OrderShowerSpacePoints(std::vector< art::Ptr< recob::SpacePoint > > &showersps, geo::Point_t const &vertex, geo::Vector_t const &direction) const
double SpacePointCharge(art::Ptr< recob::SpacePoint > const &sp, art::FindManyP< recob::Hit > const &fmh) const
geo::Point_t ShowerCentre(std::vector< art::Ptr< recob::SpacePoint > > const &showersps) const
double SpacePointTime(art::Ptr< recob::SpacePoint > const &sp, art::FindManyP< recob::Hit > const &fmh) const
double DistanceBetweenSpacePoints(art::Ptr< recob::SpacePoint > const &sp_a, art::Ptr< recob::SpacePoint > const &sp_b) const
double SpacePointProjection(art::Ptr< recob::SpacePoint > const &sp, geo::Point_t const &vertex, geo::Vector_t const &direction) const