ShowerTrackPCADirection_tool.cc
Go to the documentation of this file.
1 //############################################################################
2 //### Name: ShowerTrackPCADirection ###
3 //### Author: Dominic Barker ###
4 //### Date: 13.05.19 ###
5 //### Description: Tool for finding the shower direction using PCA ###
6 //### methods using the initial track hits ###
7 //############################################################################
8 
9 //Framework Includes
11 
12 //LArSoft Includes
14 
15 //Root Includes
16 #include "TPrincipal.h"
17 
18 namespace ShowerRecoTools {
19 
21 
22  public:
24 
25  //Generic Direction Finder
26  int CalculateElement(const art::Ptr<recob::PFParticle>& pfparticle,
28  reco::shower::ShowerElementHolder& ShowerEleHolder) override;
29 
30  private:
31  TVector3 ShowerPCAVector(const detinfo::DetectorClocksData& clockData,
32  const detinfo::DetectorPropertiesData& detProp,
33  std::vector<art::Ptr<recob::SpacePoint>>& spacePoints_pfp,
34  const art::FindManyP<recob::Hit>& fmh,
35  TVector3& ShowerCentre);
36 
37  //fcl
40  int fVerbose;
41  bool fChargeWeighted; //Should we charge weight the PCA.
42  unsigned int fMinPCAPoints; //Number of spacepoints needed to do the analysis.
43 
47  };
48 
50  : IShowerTool(pset.get<fhicl::ParameterSet>("BaseTools"))
51  , fPFParticleLabel(pset.get<art::InputTag>("PFParticleLabel"))
52  , fHitModuleLabel(pset.get<art::InputTag>("HitModuleLabel"))
53  , fVerbose(pset.get<int>("Verbose"))
54  , fChargeWeighted(pset.get<bool>("ChargeWeighted"))
55  , fMinPCAPoints(pset.get<unsigned int>("MinPCAPoints"))
56  , fShowerStartPositionInputLabel(pset.get<std::string>("ShowerStartPositionInputLabel"))
57  , fInitialTrackSpacePointsInputLabel(pset.get<std::string>("InitialTrackSpacePointsInputLabel"))
58  , fShowerDirectionOutputLabel(pset.get<std::string>("ShowerDirectionOutputLabel"))
59  {}
60 
61  int
63  art::Event& Event,
64  reco::shower::ShowerElementHolder& ShowerEleHolder)
65  {
66 
67  if (!ShowerEleHolder.CheckElement(fShowerStartPositionInputLabel)) {
68  if (fVerbose)
69  mf::LogError("ShowerTrackPCA") << "Start Position not set. Stopping" << std::endl;
70  ;
71  return 1;
72  }
73  if (!ShowerEleHolder.CheckElement(fInitialTrackSpacePointsInputLabel)) {
74  if (fVerbose)
75  mf::LogError("ShowerTrackPCA") << "TrackSpacePoints not set, returning " << std::endl;
76  return 1;
77  }
78 
79  //Get the spacepoints handle and the hit assoication
80  auto const spHandle = Event.getValidHandle<std::vector<recob::SpacePoint>>(fPFParticleLabel);
81 
82  const art::FindManyP<recob::Hit>& fmh =
83  ShowerEleHolder.GetFindManyP<recob::Hit>(spHandle, Event, fPFParticleLabel);
84 
85  std::vector<art::Ptr<recob::SpacePoint>> trackSpacePoints;
86  ShowerEleHolder.GetElement(fInitialTrackSpacePointsInputLabel, trackSpacePoints);
87 
88  //We cannot progress with no spacepoints.
89  if (trackSpacePoints.size() < fMinPCAPoints) {
90  if (fVerbose)
91  mf::LogError("ShowerTrackPCA") << "Not enough spacepoints for PCA, returning " << std::endl;
92  return 1;
93  }
94 
95  auto const clockData =
97  auto const detProp =
99 
100  //Find the PCA vector
101  TVector3 trackCentre;
102  TVector3 Eigenvector = ShowerPCAVector(clockData, detProp, trackSpacePoints, fmh, trackCentre);
103 
104  //Get the General direction as the vector between the start position and the centre
105  TVector3 StartPositionVec = {-999, -999, -999};
106  ShowerEleHolder.GetElement(fShowerStartPositionInputLabel, StartPositionVec);
107  TVector3 GeneralDir = (trackCentre - StartPositionVec).Unit();
108 
109  //Dot product
110  double DotProduct = Eigenvector.Dot(GeneralDir);
111 
112  //If the dotproduct is negative the Direction needs Flipping
113  if (DotProduct < 0) {
114  Eigenvector[0] = -Eigenvector[0];
115  Eigenvector[1] = -Eigenvector[1];
116  Eigenvector[2] = -Eigenvector[2];
117  }
118 
119  TVector3 EigenvectorErr = {-999, -999, -999};
120 
121  ShowerEleHolder.SetElement(Eigenvector, EigenvectorErr, fShowerDirectionOutputLabel);
122 
123  return 0;
124  }
125 
126  //Function to calculate the shower direction using a charge weight 3D PCA calculation.
127  TVector3
129  const detinfo::DetectorPropertiesData& detProp,
131  const art::FindManyP<recob::Hit>& fmh,
132  TVector3& ShowerCentre)
133  {
134 
135  //Initialise the the PCA.
136  TPrincipal* pca = new TPrincipal(3, "");
137 
138  float TotalCharge = 0;
139 
140  //Get the Shower Centre
141  ShowerCentre =
142  IShowerTool::GetLArPandoraShowerAlg().ShowerCentre(clockData, detProp, sps, fmh, TotalCharge);
143 
144  //Normalise the spacepoints, charge weight and add to the PCA.
145  for (auto& sp : sps) {
146 
147  TVector3 sp_position = IShowerTool::GetLArPandoraShowerAlg().SpacePointPosition(sp);
148 
149  float wht = 1;
150 
151  //Normalise the spacepoint position.
152  sp_position = sp_position - ShowerCentre;
153 
154  if (fChargeWeighted) {
155 
156  //Get the charge.
157  float Charge = IShowerTool::GetLArPandoraShowerAlg().SpacePointCharge(sp, fmh);
158 
159  //Get the time of the spacepoint
160  float Time = IShowerTool::GetLArPandoraShowerAlg().SpacePointTime(sp, fmh);
161 
162  //Correct for the lifetime at the moment.
163  Charge *= std::exp((sampling_rate(clockData) * Time) / (detProp.ElectronLifetime() * 1e3));
164 
165  //Charge Weight
166  wht *= std::sqrt(Charge / TotalCharge);
167  }
168 
169  double sp_coord[3];
170  sp_coord[0] = sp_position.X() * wht;
171  sp_coord[1] = sp_position.Y() * wht;
172  sp_coord[2] = sp_position.Z() * wht;
173 
174  //Add to the PCA
175  pca->AddRow(sp_coord);
176  }
177 
178  //Evaluate the PCA
179  pca->MakePrincipals();
180 
181  //Get the Eigenvectors.
182  const TMatrixD* Eigenvectors = pca->GetEigenVectors();
183 
184  TVector3 Eigenvector = {(*Eigenvectors)[0][0], (*Eigenvectors)[1][0], (*Eigenvectors)[2][0]};
185 
186  delete pca;
187 
188  return Eigenvector;
189  }
190 }
191 
#define DEFINE_ART_CLASS_TOOL(tool)
Definition: ToolMacros.h:42
ShowerTrackPCADirection(const fhicl::ParameterSet &pset)
std::string string
Definition: nybbler.cc:12
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)
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
double SpacePointTime(art::Ptr< recob::SpacePoint > const &sp, art::FindManyP< recob::Hit > const &fmh) const
ValidHandle< PROD > getValidHandle(InputTag const &tag) const
Definition: DataViewImpl.h:441
bool CheckElement(const std::string &Name) const
int GetElement(const std::string &Name, T &Element) const
const shower::LArPandoraShowerAlg & GetLArPandoraShowerAlg() const
Definition: IShowerTool.h:87
double SpacePointCharge(art::Ptr< recob::SpacePoint > const &sp, art::FindManyP< recob::Hit > const &fmh) const
Contains all timing reference information for the detector.
Definition: types.h:32
TVector3 ShowerCentre(std::vector< art::Ptr< recob::SpacePoint >> const &showersps) const
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
double sampling_rate(DetectorClocksData const &data)
Returns the period of the TPC readout electronics clock.
int CalculateElement(const art::Ptr< recob::PFParticle > &pfparticle, art::Event &Event, reco::shower::ShowerElementHolder &ShowerEleHolder) override
int bool
Definition: qglobal.h:345
TVector3 ShowerPCAVector(const detinfo::DetectorClocksData &clockData, const detinfo::DetectorPropertiesData &detProp, std::vector< art::Ptr< recob::SpacePoint >> &spacePoints_pfp, const art::FindManyP< recob::Hit > &fmh, TVector3 &ShowerCentre)
QTextStream & endl(QTextStream &s)
TVector3 SpacePointPosition(art::Ptr< recob::SpacePoint > const &sp) const