48 const detinfo::DetectorClocksData& clockData,
49 const detinfo::DetectorPropertiesData& detProp,
50 const std::vector<art::Ptr<recob::SpacePoint>>& spacePoints_pfp,
51 const art::FindManyP<recob::Hit>& fmh,
52 geo::Point_t& ShowerCentre);
72 :
IShowerTool(pset.get<fhicl::ParameterSet>(
"BaseTools"))
73 , fPFParticleLabel(pset.get<
art::InputTag>(
"PFParticleLabel"))
74 , fVerbose(pset.get<int>(
"Verbose"))
75 , fNSegments(pset.get<unsigned int>(
"NSegments"))
76 , fUseStartPosition(pset.get<bool>(
"UseStartPosition"))
77 , fChargeWeighted(pset.get<bool>(
"ChargeWeighted"))
78 , fShowerStartPositionInputLabel(pset.get<std::string>(
"ShowerStartPositionInputLabel"))
79 , fShowerDirectionOutputLabel(pset.get<std::string>(
"ShowerDirectionOutputLabel"))
80 , fShowerCentreOutputLabel(pset.get<std::string>(
"ShowerCentreOutputLabel"))
81 , fShowerPCAOutputLabel(pset.get<std::string>(
"ShowerPCAOutputLabel"))
97 auto const pfpHandle = Event.getValidHandle<std::vector<recob::PFParticle>>(
fPFParticleLabel);
99 const art::FindManyP<recob::SpacePoint>& fmspp =
103 auto const spHandle = Event.getValidHandle<std::vector<recob::SpacePoint>>(
fPFParticleLabel);
105 const art::FindManyP<recob::Hit>& fmh =
109 std::vector<art::Ptr<recob::SpacePoint>> spacePoints_pfp = fmspp.at(pfparticle.key());
112 if (spacePoints_pfp.size() < 3) {
113 mf::LogWarning(
"ShowerPCADirection")
114 << spacePoints_pfp.size() <<
" spacepoints in shower, not calculating direction"
119 auto const clockData =
120 art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(Event);
122 art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(Event, clockData);
125 geo::Point_t ShowerCentre;
126 recob::PCAxis PCA =
CalculateShowerPCA(clockData, detProp, spacePoints_pfp, fmh, ShowerCentre);
130 geo::Point_t ShowerCentreErr = {-999, -999, -999};
138 mf::LogError(
"ShowerPCADirection")
139 <<
"fUseStartPosition is set but ShowerStartPosition is not set. Bailing" << std::endl;
143 geo::Point_t StartPositionVec = {-999, -999, -999};
147 auto const GeneralDir = (ShowerCentre - StartPositionVec).Unit();
150 double DotProduct = PCADirection.Dot(GeneralDir);
153 if (DotProduct < 0) { PCADirection *= -1; }
156 geo::Vector_t PCADirectionErr = {-999, -999, -999};
163 spacePoints_pfp, ShowerCentre, PCADirection,
fNSegments);
167 if (RMSGradient < -std::numeric_limits<double>::epsilon()) { PCADirection *= -1; }
170 geo::Vector_t PCADirectionErr = {-999, -999, -999};
178 const detinfo::DetectorClocksData& clockData,
179 const detinfo::DetectorPropertiesData& detProp,
180 const std::vector<art::Ptr<recob::SpacePoint>>& sps,
181 const art::FindManyP<recob::Hit>& fmh,
182 geo::Point_t& ShowerCentre)
185 float TotalCharge = 0;
186 float sumWeights = 0;
197 clockData, detProp, sps, fmh, TotalCharge);
204 for (
auto& sp : sps) {
209 auto const sp_position = sp->position() - ShowerCentre;
220 Charge *= std::exp((sampling_rate(clockData) * Time) / (detProp.ElectronLifetime() * 1e3));
223 wht *= std::sqrt(Charge / TotalCharge);
226 xx += sp_position.X() * sp_position.X() * wht;
227 yy += sp_position.Y() * sp_position.Y() * wht;
228 zz += sp_position.Z() * sp_position.Z() * wht;
229 xy += sp_position.X() * sp_position.Y() * wht;
230 xz += sp_position.X() * sp_position.Z() * wht;
231 yz += sp_position.Y() * sp_position.Z() * wht;
236 Eigen::Matrix3f matrix;
239 matrix << xx, xy, xz, xy, yy, yz, xz, yz, zz;
242 matrix /= sumWeights;
245 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3f> eigenMatrix(matrix);
247 Eigen::Vector3f eigenValuesVector = eigenMatrix.eigenvalues();
248 Eigen::Matrix3f eigenVectorsMatrix = eigenMatrix.eigenvectors();
251 const bool svdOk =
true;
252 const int nHits = sps.size();
254 const double eigenValues[3] = {
255 eigenValuesVector(2), eigenValuesVector(1), eigenValuesVector(0)};
256 std::vector<std::vector<double>> eigenVectors = {
257 {eigenVectorsMatrix(0, 2), eigenVectorsMatrix(1, 2), eigenVectorsMatrix(2, 2)},
258 {eigenVectorsMatrix(0, 1), eigenVectorsMatrix(1, 1), eigenVectorsMatrix(2, 1)},
259 {eigenVectorsMatrix(0, 0), eigenVectorsMatrix(1, 0), eigenVectorsMatrix(2, 0)}};
260 const double avePos[3] = {ShowerCentre.X(), ShowerCentre.Y(), ShowerCentre.Z()};
262 return recob::PCAxis(svdOk, nHits, eigenValues, eigenVectors, avePos);
279 if (
fVerbose) mf::LogError(
"ShowerPCADirection: Add Assns") <<
"PCA not set." << std::endl;
285 const art::Ptr<recob::PCAxis> pcaPtr =
287 const art::Ptr<recob::Shower> showerPtr =
288 GetProducedElementPtr<recob::Shower>(
"shower", ShowerEleHolder);
290 AddSingle<art::Assns<recob::Shower, recob::PCAxis>>(showerPtr, pcaPtr,
"ShowerPCAxisAssn");
291 AddSingle<art::Assns<recob::PFParticle, recob::PCAxis>>(pfpPtr, pcaPtr,
"PFParticlePCAxisAssn");