Pandora
Pandora source code navigator
Loading...
Searching...
No Matches
ShowerLinearEnergy_tool.cc
Go to the documentation of this file.
1//############################################################################
2//### Name: ShowerLinearEnergy ###
3//### Author: Dominic Barker ###
4//### Date: 13.05.19 ###
5//### Description: Tool for finding the Energy of the shower. Derived ###
6//### from the linear energy algorithm, written for ###
7//### the EMShower_module.cc ###
8//############################################################################
9
10//Framework Includes
11#include "art/Utilities/ToolMacros.h"
12
13//LArSoft Includes
14#include "lardata/DetectorInfoServices/DetectorClocksService.h"
15#include "lardata/DetectorInfoServices/DetectorPropertiesService.h"
16#include "lardataobj/RecoBase/Cluster.h"
17#include "lardataobj/RecoBase/Hit.h"
18#include "lardataobj/RecoBase/PFParticle.h"
20
21namespace ShowerRecoTools {
22
24
25 public:
26 ShowerLinearEnergy(const fhicl::ParameterSet& pset);
27
28 //Physics Function. Calculate the shower Energy.
29 int CalculateElement(const art::Ptr<recob::PFParticle>& pfparticle,
30 art::Event& Event,
31 reco::shower::ShowerElementHolder& ShowerElementHolder) override;
32
33 private:
34 double CalculateEnergy(const detinfo::DetectorClocksData& clockData,
35 const detinfo::DetectorPropertiesData& detProp,
36 const std::vector<art::Ptr<recob::Hit>>& hits,
37 const geo::PlaneID::PlaneID_t plane) const;
38
39 //fcl parameters
40 unsigned int fNumPlanes;
41 std::vector<double> fGradients; //Gradient of the linear fit of total charge to total energy
42 std::vector<double> fIntercepts; //Intercept of the linear fit of total charge to total energy
43
44 art::InputTag fPFParticleLabel;
46
49
50 //Services
51 art::ServiceHandle<geo::Geometry> fGeom;
52 };
53
54 ShowerLinearEnergy::ShowerLinearEnergy(const fhicl::ParameterSet& pset)
55 : IShowerTool(pset.get<fhicl::ParameterSet>("BaseTools"))
56 , fGradients(pset.get<std::vector<double>>("Gradients"))
57 , fIntercepts(pset.get<std::vector<double>>("Intercepts"))
58 , fPFParticleLabel(pset.get<art::InputTag>("PFParticleLabel"))
59 , fVerbose(pset.get<int>("Verbose"))
60 , fShowerEnergyOutputLabel(pset.get<std::string>("ShowerEnergyOutputLabel"))
61 , fShowerBestPlaneOutputLabel(pset.get<std::string>("ShowerBestPlaneOutputLabel"))
62 {
63 fNumPlanes = fGeom->Nplanes();
64 if (fNumPlanes != fGradients.size() || fNumPlanes != fIntercepts.size()) {
65 throw cet::exception("ShowerLinearEnergy")
66 << "The number of planes does not match the size of the fcl parametes passed: Num Planes: "
67 << fNumPlanes << ", Gradients size: " << fGradients.size()
68 << ", Intercpts size: " << fIntercepts.size();
69 }
70 }
71
72 int ShowerLinearEnergy::CalculateElement(const art::Ptr<recob::PFParticle>& pfparticle,
73 art::Event& Event,
74 reco::shower::ShowerElementHolder& ShowerEleHolder)
75 {
76
77 // Get the assocated pfParicle vertex PFParticles
78 auto const pfpHandle = Event.getValidHandle<std::vector<recob::PFParticle>>(fPFParticleLabel);
79
80 //Get the clusters
81 auto const clusHandle = Event.getValidHandle<std::vector<recob::Cluster>>(fPFParticleLabel);
82
83 const art::FindManyP<recob::Cluster>& fmc =
84 ShowerEleHolder.GetFindManyP<recob::Cluster>(pfpHandle, Event, fPFParticleLabel);
85 // art::FindManyP<recob::Cluster> fmc(pfpHandle, Event, fPFParticleLabel);
86 std::vector<art::Ptr<recob::Cluster>> clusters = fmc.at(pfparticle.key());
87
88 //Get the hit association
89 const art::FindManyP<recob::Hit>& fmhc =
90 ShowerEleHolder.GetFindManyP<recob::Hit>(clusHandle, Event, fPFParticleLabel);
91 // art::FindManyP<recob::Hit> fmhc(clusHandle, Event, fPFParticleLabel);
92
93 std::map<geo::PlaneID::PlaneID_t, std::vector<art::Ptr<recob::Hit>>> planeHits;
94
95 //Loop over the clusters in the plane and get the hits
96 for (auto const& cluster : clusters) {
97
98 //Get the hits
99 std::vector<art::Ptr<recob::Hit>> hits = fmhc.at(cluster.key());
100
101 //Get the plane.
102 const geo::PlaneID::PlaneID_t plane(cluster->Plane().Plane);
103
104 planeHits[plane].insert(planeHits[plane].end(), hits.begin(), hits.end());
105 }
106
107 // Calculate the energy for each plane && best plane
108 geo::PlaneID::PlaneID_t bestPlane = std::numeric_limits<geo::PlaneID::PlaneID_t>::max();
109 unsigned int bestPlaneNumHits = 0;
110
111 //Holder for the final product
112 std::vector<double> energyVec(fNumPlanes, -999.);
113 std::vector<double> energyError(fNumPlanes, -999.);
114
115 auto const clockData =
116 art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(Event);
117 auto const detProp =
118 art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(Event, clockData);
119
120 for (auto const& [plane, hits] : planeHits) {
121
122 unsigned int planeNumHits = hits.size();
123
124 //Calculate the Energy for
125 double Energy = CalculateEnergy(clockData, detProp, hits, plane);
126 // If the energy is negative, leave it at -999
127 if (Energy > 0) energyVec.at(plane) = Energy;
128
129 if (planeNumHits > bestPlaneNumHits) {
130 bestPlane = plane;
131 bestPlaneNumHits = planeNumHits;
132 }
133 }
134
135 ShowerEleHolder.SetElement(energyVec, energyError, fShowerEnergyOutputLabel);
136 // Only set the best plane if it has some hits in it
137 if (bestPlane < fGeom->Nplanes()) {
138 // Need to cast as an int for legacy default of -999
139 // have to define a new variable as we pass-by-reference when filling
140 int bestPlaneVal(bestPlane);
141 ShowerEleHolder.SetElement(bestPlaneVal, fShowerBestPlaneOutputLabel);
142 }
143
144 return 0;
145 }
146
147 //Function to calculate the energy of a shower in a plane. Using a linear map between charge and Energy.
148 //Exactly the same method as the ShowerEnergyAlg.cxx. Thanks Mike.
149 double ShowerLinearEnergy::CalculateEnergy(const detinfo::DetectorClocksData& clockData,
150 const detinfo::DetectorPropertiesData& detProp,
151 const std::vector<art::Ptr<recob::Hit>>& hits,
152 const geo::PlaneID::PlaneID_t plane) const
153 {
154
155 double totalCharge = 0, totalEnergy = 0;
156
157 for (auto const& hit : hits) {
158 totalCharge += (hit->Integral() * std::exp((sampling_rate(clockData) * hit->PeakTime()) /
159 (detProp.ElectronLifetime() * 1e3)));
160 }
161
162 totalEnergy = (totalCharge * fGradients.at(plane)) + fIntercepts.at(plane);
163
164 return totalEnergy;
165 }
166}
167
168DEFINE_ART_CLASS_TOOL(ShowerRecoTools::ShowerLinearEnergy)
double CalculateEnergy(const detinfo::DetectorClocksData &clockData, const detinfo::DetectorPropertiesData &detProp, const std::vector< art::Ptr< recob::Hit > > &hits, const geo::PlaneID::PlaneID_t plane) const
ShowerLinearEnergy(const fhicl::ParameterSet &pset)
art::ServiceHandle< geo::Geometry > fGeom
int CalculateElement(const art::Ptr< recob::PFParticle > &pfparticle, art::Event &Event, reco::shower::ShowerElementHolder &ShowerElementHolder) override
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)