10#include "art/Utilities/ToolMacros.h"
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"
22#include "Math/RotationX.h"
23#include "Math/RotationY.h"
24#include "Math/RotationZ.h"
27#include "TPrincipal.h"
43 const art::Event& Event,
44 std::vector<art::Ptr<recob::SpacePoint>>
const& sps,
45 const art::FindManyP<recob::Hit>& fmh);
48 std::vector<art::Ptr<recob::SpacePoint>>
const& initial_track);
50 void PruneTrack(std::vector<art::Ptr<recob::SpacePoint>>& initial_track);
53 std::vector<art::Ptr<recob::SpacePoint>>& sps_pool,
54 size_t num_sps_to_take);
56 bool IsSegmentValid(std::vector<art::Ptr<recob::SpacePoint>>
const& segment);
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);
66 const detinfo::DetectorPropertiesData& detProp,
67 std::vector<art::Ptr<recob::SpacePoint>>& segment,
68 const art::FindManyP<recob::Hit>& fmh);
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);
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);
84 bool IsResidualOK(
double new_residual,
double current_residual)
const
92 bool IsResidualOK(
double new_residual,
double current_residual,
size_t no_sps)
const
98 geo::Vector_t
const& PCAEigenvector,
99 geo::Point_t
const& TrackPosition)
const;
102 geo::Vector_t
const& PCAEigenvector,
103 geo::Point_t
const& TrackPosition,
104 int& max_residual_point)
const;
107 geo::Vector_t
ShowerPCAVector(std::vector<art::Ptr<recob::SpacePoint>>
const& sps)
const;
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;
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,
121 const art::FindManyP<recob::Hit>& dud_fmh);
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);
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"))
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"))
169 fInitialTrackHitsOutputLabel(pset.get<std::string>(
"InitialTrackHitsOutputLabel"))
170 , fInitialTrackSpacePointsOutputLabel(
171 pset.get<std::string>(
"InitialTrackSpacePointsOutputLabel"))
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";
181 const art::Ptr<recob::PFParticle>& pfparticle,
189 mf::LogError(
"ShowerIncrementalTrackHitFinder")
190 <<
"Start position not set, returning " << std::endl;
195 auto const pfpHandle = Event.getValidHandle<std::vector<recob::PFParticle>>(
fPFParticleLabel);
198 const art::FindManyP<recob::SpacePoint>& fmspp =
202 auto const spHandle = Event.getValidHandle<std::vector<recob::SpacePoint>>(
fPFParticleLabel);
205 const art::FindManyP<recob::Hit>& fmh =
209 std::vector<art::Ptr<recob::SpacePoint>> spacePoints = fmspp.at(pfparticle.key());
212 if (spacePoints.empty()) {
214 mf::LogError(
"ShowerIncrementalTrackHitFinder")
215 <<
"No space points, returning " << std::endl;
219 geo::Point_t ShowerStartPosition = {-999, -999, -999};
227 mf::LogError(
"ShowerIncrementalTrackHitFinder")
228 <<
"Direction not set, returning " << std::endl;
232 geo::Vector_t ShowerDirection = {-999, -999, -999};
237 spacePoints, ShowerStartPosition, ShowerDirection);
241 for (
auto spacePoint : spacePoints) {
243 spacePoint, ShowerStartPosition, ShowerDirection);
244 if (proj < 0) { ++back_sps; }
245 if (proj > 0) {
break; }
247 spacePoints.erase(spacePoints.begin(), spacePoints.begin() + back_sps);
253 ShowerStartPosition);
258 for (
auto const& spacePoint : spacePoints) {
259 double dist = (spacePoint->position() - ShowerStartPosition).R();
263 spacePoints.erase(spacePoints.begin(), spacePoints.begin() + frontsp);
267 for (
auto const& spacePoint : spacePoints) {
268 double dist = (spacePoint->position() - ShowerStartPosition).R();
272 spacePoints.erase(spacePoints.begin() + sp_iter, spacePoints.end());
274 if (spacePoints.size() < 3) {
276 mf::LogError(
"ShowerIncrementalTrackHitFinder")
277 <<
"Not enough spacepoints bailing" << std::endl;
285 std::vector<art::Ptr<recob::SpacePoint>> track_sps =
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);
305 std::vector<art::Ptr<recob::SpacePoint>>
const& sps)
const
308 TPrincipal pca(3,
"");
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);
318 pca.MakePrincipals();
321 const TMatrixD* Eigenvectors = pca.GetEigenVectors();
323 return {(*Eigenvectors)[0][0], (*Eigenvectors)[1][0], (*Eigenvectors)[2][0]};
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
333 TPrincipal pca(3,
"");
335 float TotalCharge = 0;
338 for (
auto& sp : sps) {
339 auto const sp_position = sp->position();
348 Charge *= std::exp((sampling_rate(clockData) * Time) / (detProp.ElectronLifetime() * 1e3));
351 wht *= std::sqrt(Charge / TotalCharge);
354 double sp_coord[3] = {sp_position.X() * wht, sp_position.Y() * wht, sp_position.Z() * wht};
355 pca.AddRow(sp_coord);
359 pca.MakePrincipals();
362 const TMatrixD* Eigenvectors = pca.GetEigenVectors();
364 return {(*Eigenvectors)[0][0], (*Eigenvectors)[1][0], (*Eigenvectors)[2][0]};
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)
378 int maxresidual_point = 0;
388 while (!ok && segment.size() != 1) {
391 for (
auto sp = segment.begin(); sp != segment.end(); ++sp) {
392 if (sp->key() == (unsigned)maxresidual_point) {
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)
414 auto const clockData =
415 art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(Event);
417 art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(Event, clockData);
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;
424 while (sps_pool.size() > 0) {
427 std::vector<art::Ptr<recob::SpacePoint>> track_segment;
438 if (track_segment.empty())
break;
440 track_segment_copy = track_segment;
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();
455 if (initial_segment_size == track_segment.size()) {
469 if (
fMakeTrackSeed && initial_track.empty()) initial_track = track_segment_copy;
474 return initial_track;
478 std::vector<art::Ptr<recob::SpacePoint>>& sps_pool,
479 std::vector<art::Ptr<recob::SpacePoint>>
const& initial_track)
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());
495 std::vector<art::Ptr<recob::SpacePoint>>& initial_track)
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);
513 std::vector<art::Ptr<recob::SpacePoint>>& segment,
514 std::vector<art::Ptr<recob::SpacePoint>>& sps_pool,
515 size_t num_sps_to_take)
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());
526 std::vector<art::Ptr<recob::SpacePoint>>
const& segment)
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)
545 if (sps_pool.empty())
return !ok;
553 ok =
IsResidualOK(residual, current_residual, segment.size());
556 std::vector<art::Ptr<recob::SpacePoint>> sub_sps_pool;
560 std::vector<art::Ptr<recob::SpacePoint>> sub_sps_pool_cache = sub_sps_pool;
564 sub_sps_pool_cache.insert(sub_sps_pool_cache.begin(), segment.back());
566 clockData, detProp, segment, sub_sps_pool, fmh, current_residual);
571 while (sub_sps_pool.size() > 0) {
572 sps_pool.insert(sps_pool.begin(), sub_sps_pool.back());
573 sub_sps_pool.pop_back();
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();
593 current_residual = residual;
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)
606 geo::Vector_t primary_axis;
612 geo::Point_t segment_centre;
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)
629 geo::Vector_t primary_axis;
635 geo::Point_t segment_centre;
642 return CalculateResidual(segment, primary_axis, segment_centre, max_residual_point);
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)
656 if (reduced_sps_pool.empty())
return !ok;
663 ok =
IsResidualOK(residual, current_residual, segment.size());
667 clockData, detProp, segment, reduced_sps_pool, fmh, current_residual);
671 std::vector<art::Ptr<recob::SpacePoint>>& sps,
672 geo::Vector_t
const& PCAEigenvector,
673 geo::Point_t
const& TrackPosition)
const
677 for (
auto const& sp : sps) {
680 auto const pos = sp->position() - TrackPosition;
683 double len = pos.Dot(PCAEigenvector);
684 double perp = (pos - len * PCAEigenvector).R();
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
698 double max_residual = -999;
700 for (
auto const& sp : sps) {
703 auto const pos = sp->position() - TrackPosition;
706 double len = pos.Dot(PCAEigenvector);
707 double perp = (pos - len * PCAEigenvector).R();
711 if (perp > max_residual) {
713 max_residual_point = sp.key();
719 std::vector<art::Ptr<recob::SpacePoint>>
721 geo::Vector_t
const& start_direction)
723 std::vector<art::Ptr<recob::SpacePoint>> fake_sps;
724 std::vector<art::Ptr<recob::SpacePoint>> segment_a =
726 fake_sps.insert(std::end(fake_sps), std::begin(segment_a), std::end(segment_a));
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 =
733 fake_sps.insert(std::end(fake_sps), std::begin(segment_b), std::end(segment_b));
736 auto const branching_position = fake_sps.back()->position();
738 auto const direction_branch_a = ROOT::Math::RotationZ{15. * 3.142 / 180.}(direction);
739 std::vector<art::Ptr<recob::SpacePoint>> branch_a =
741 fake_sps.insert(std::end(fake_sps), std::begin(branch_a), std::end(branch_a));
743 auto const direction_branch_b = ROOT::Math::RotationY{20. * 3.142 / 180.}(direction);
744 std::vector<art::Ptr<recob::SpacePoint>> branch_b =
746 fake_sps.insert(std::end(fake_sps), std::begin(branch_b), std::end(branch_b));
748 auto const direction_branch_c = ROOT::Math::RotationX{3. * 3.142 / 180.}(direction);
749 std::vector<art::Ptr<recob::SpacePoint>> branch_c =
751 fake_sps.insert(std::end(fake_sps), std::begin(branch_c), std::end(branch_c));
757 geo::Point_t
const& start_position,
758 geo::Vector_t
const& start_direction,
761 std::vector<art::Ptr<recob::SpacePoint>> fake_sps;
762 art::ProductID prod_id(std::string(
"totally_genuine"));
763 size_t current_id = 500000;
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++));
777 const art::Event& Event,
778 const art::FindManyP<recob::Hit>& dud_fmh)
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 =
787 std::vector<art::Ptr<recob::SpacePoint>> track_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]);
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]);
805 art::ServiceHandle<art::TFileService> tfs;
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);
814 graph_track_sps.SetMarkerStyle(8);
815 graph_track_sps.SetMarkerColor(2);
816 graph_track_sps.SetFillColor(2);
817 graph_track_sps.Draw(
"samep");
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