ShowerProcess.h
Go to the documentation of this file.
1 #ifndef SHOWER_PROCESS_H
2 #define SHOWER_PROCESS_H
3 
4 #include <iostream>
5 #include <vector>
6 #include <string>
7 
8 // Larsoft includes
14 
17 #include "Cone.h"
18 
19 #include "TFile.h"
20 #include "TH3F.h"
21 
22 namespace pizero {
23 
24 // Class to store all relevant objects and variables of a shower process.
26  private:
27  // Shower process objects.
28  std::vector<const simb::MCParticle*> m_mcparts;
29  std::vector<const recob::Shower*> m_showers;
30  std::vector<const recob::Track*> m_tracks;
31  // double cone_length = 100;
32  // double cone_width = 20;
33  Cone* m_cone = nullptr;
34 
35  // Event information.
36  const art::Event* m_evt;
42 
43  // MCParticle and reconstructed object finders.
44  void find_mcparticles();
45  void find_showers();
46  void find_tracks();
47  void fill_cone();
48 
49  // Utilities for convenience.
52 
53  public:
54  // Constructors from MCParticle, shower and both.
56  const art::Event& evt,
57  detinfo::DetectorClocksData const& clockData,
58  detinfo::DetectorPropertiesData const& detProp,
59  std::string showerLabel = "pandoraShower",
60  std::string trackLabel = "pandoraTrack",
61  std::string simulationLabel = "largeant"):
62  m_evt(&evt),
63  m_clockdata(&clockData),
64  m_detprop(&detProp),
65  m_showerLabel(showerLabel),
66  m_trackLabel(trackLabel),
67  m_simulationLabel(simulationLabel) {
68  m_mcparts.push_back(&mcpart);
69  find_showers();
70  find_tracks();
71  fill_cone();
72  }
74  detinfo::DetectorClocksData const& clockData,
75  detinfo::DetectorPropertiesData const& detProp,
76  std::string showerLabel = "pandoraShower",
77  std::string trackLabel = "pandoraTrack",
78  std::string simulationLabel = "largeant"):
79  m_evt(&evt),
80  m_clockdata(&clockData),
81  m_detprop(&detProp),
82  m_showerLabel(showerLabel),
83  m_trackLabel(trackLabel),
84  m_simulationLabel(simulationLabel) {
85  m_showers.push_back(&shower);
87  find_tracks();
88  fill_cone();
89  }
91  const art::Event& evt,
92  detinfo::DetectorClocksData const& clockData,
93  detinfo::DetectorPropertiesData const& detProp,
94  std::string showerLabel = "pandoraShower",
95  std::string trackLabel = "pandoraTrack",
96  std::string simulationLabel = "largeant"):
97  m_evt(&evt),
98  m_clockdata(&clockData),
99  m_detprop(&detProp),
100  m_showerLabel(showerLabel),
101  m_trackLabel(trackLabel),
102  m_simulationLabel(simulationLabel) {
103  m_mcparts.push_back(&mcpart);
104  m_showers.push_back(&shower);
105  find_tracks();
106  fill_cone();
107  }
108  ~ShowerProcess() { if(m_cone != nullptr) delete m_cone; } // TODO: make unique_ptr.
109 
110  // Related object getters. The elements are guaranteed to be descending in energy.
111  const simb::MCParticle* mcparticle() const {
112  return m_mcparts.size()!=0? m_mcparts[0]: nullptr;
113  }
114  const recob::Shower* shower() const {
115  return m_showers.size()!=0? m_showers[0]: nullptr;
116  }
117  const recob::Track* track() const {
118  return m_tracks.size()!=0? m_tracks[0]: nullptr;
119  }
120  const Cone* cone() const {
121  return m_cone;
122  }
123  // Object vector getters.
124  std::vector<const simb::MCParticle*> mcparticles() const { return m_mcparts; }
125  std::vector<const recob::Shower*> showers() const { return m_showers; }
126  std::vector<const recob::Track*> tracks() const { return m_tracks; }
127  // Calorimetry.
128  double energy(const std::string& caloLabel, const double calib,
129  const double norm, const std::string& scefile, const std::string& yzfile,
130  const std::string& xfile) const;
131 }; // class ShowerProcess
132 
133 
134 // Find MCParticle based on the biggest shower via truth utilities.
136  if(m_evt->isRealData() || m_showers.size() == 0) return;
138 }
139 
140 // Find showers based on the given MCParticle.
142  if(m_mcparts.size() == 0) return;
143 
144  // Find all showers this MCParticle contributed to.
145  std::vector<std::pair<const recob::Shower*, double>> showers =
147  // Only showers to which the MCParticle was the primary contributor are saved.
148  for(const std::pair<const recob::Shower*, double>& sh : showers) {
149  const simb::MCParticle* sh_part =
151  if(std::abs(sh_part->TrackId()) == std::abs(m_mcparts[0]->TrackId())) {
152  m_showers.push_back(sh.first);
153  }
154  }
155 }
156 
157 // Find tracks based on the given MCParticle or shower if no MC is present.
159  // For now return if no MC present.
160  if(m_mcparts.size() == 0) return;
161 
162  using weightedTrackPair = std::pair<const recob::Track*, double>;
163  std::vector<weightedTrackPair> outVec;
164 
165  // Get all reconstructed tracks
166  auto allRecoTracks = m_evt->getValidHandle<std::vector<recob::Track> >(m_trackLabel);
167 
168  // We need the association between the tracks and the hits
169  const art::FindManyP<recob::Hit> findTrackHits(allRecoTracks, *m_evt, m_trackLabel);
170 
173  std::unordered_map<int, double> recoTrack;
174 
175  // Record the energy contribution to the MCParticle of every relevant reco track
176  double part_E = 0;
177  for (recob::Track const & track : *allRecoTracks) {
178  // Record the contribution of all MCParticles to this track.
179  std::unordered_map<int, double> mcpmap;
180  // Loop through the track's hits.
181  for (art::Ptr<recob::Hit> const & hptr : findTrackHits.at(track.ID())) {
182  // Loop over hit IDEs to find our MCParticle's part in it
183  for (const sim::IDE* ide : bt_serv->HitToSimIDEs_Ps(*m_clockdata, hptr)) {
184  mcpmap[abs(ide->trackID)] += ide->energy;
185  if (abs(ide->trackID) == mcparticle()->TrackId()) {
186  recoTrack[track.ID()] += ide->energy;
187  }
188  part_E += ide->energy;
189  } // sim::IDE*
190  } // art::Ptr<recob::Hit>
191 
192  // Remove track if the shower's MCParticle was not the main contributor.
193  if(recoTrack.size() > 0) {
194  int maxMCPID = mcpmap[0];
195  if(mcpmap.size() > 1) {
196  maxMCPID = std::max_element(mcpmap.begin(), mcpmap.end(),
197  [](const std::pair<int, double>& a, const std::pair<int, double>& b){
198  return a.second < b.second;
199  })->first;
200  }
201  if(maxMCPID != mcparticle()->TrackId()) {
202  recoTrack.erase(track.ID());
203  }
204  }
205  } // const recob::Track&
206  // for(auto const& p : recoTrack) {
207  // std::cout << "Track with ID " << p.first << " has energy " << p.second << '\n';
208  // }
209 
210  // Fill and sort the output vector
211  for (std::pair<int, double> const& p : recoTrack)
212  {
213  auto const trackIt = std::find_if(allRecoTracks->begin(), allRecoTracks->end(),
214  [&](recob::Track tr){ return tr.ID() == p.first; });
215  outVec.push_back(std::make_pair(&*trackIt, p.second));
216  }
217  std::sort(outVec.begin(), outVec.end(),
218  [](weightedTrackPair a, weightedTrackPair b){ return a.second > b.second;});
219 
220  // Normalise the vector weights
221  if (part_E < 1e-5) { part_E = 1; } // Protect against zero division
222  for (weightedTrackPair& p : outVec)
223  {
224  p.second /= part_E;
225  m_tracks.push_back(p.first);
226  }
227 
228  // // Find all tracks this MCParticle contributed to.
229  // std::vector<std::pair<const recob::Track*, double>> tracks =
230  // truthUtils.GetRecoTrackListFromMCParticle(*m_mcparts[0], *m_evt, m_trackLabel);
231  // // Only tracks to which the MCParticle was the primary contributor are saved.
232  // for(const std::pair<const recob::Track*, double>& tr : tracks) {
233  // const simb::MCParticle* tr_part =
234  // truthUtils.GetMCParticleFromReco(*tr.first, *m_evt, m_trackLabel);
235  // if(std::abs(tr_part->TrackId()) == std::abs(m_mcparts[0]->TrackId())) {
236  // m_tracks.push_back(tr.first);
237  // }
238  // }
239 }
240 
241 // Fill the cone object based on the showers and tracks in the class.
243  // TODO: Find the start and direction of first reconstructed object.
244  TVector3 cstart, cdir;
245  if(m_showers.size() != 0) {
246  cstart = m_showers[0]->ShowerStart();
247  cdir = m_showers[0]->Direction();
248  // Make cone object
249  m_cone = new Cone(*m_evt, *m_clockdata, *m_detprop, cstart, cdir, m_showers[0]->Length());
250  }
251  // else if(m_tracks.size() != 0) {
252  // const recob::tracking::Point_t tstart = m_tracks[0]->Start();
253  // const recob::tracking::Vector_t tdir = m_tracks[0]->StartDirection();
254  // cstart = TVector3(tstart.X(), tstart.Y(), tstart.Z());
255  // cdir = TVector3(tdir.X(), tdir.Y(), tdir.Z());
256  // }
257 
258 }
259 
260 double ShowerProcess::energy(const std::string& caloLabel, const double calib,
261  const double norm, const std::string& scefile, const std::string& yzfile,
262  const std::string& xfile) const {
263  double totE = 0;
264 
265  // Check whether there is a shower associated with this object.
266  if(shower() == nullptr) return totE;
267 
268  // Constants from DUNE docDB 15974 by A Paudel.
269  const double Wion = 23.6e-6; // ArgoNeuT-determined parameter at E0 kV/cm
270  const double recob = 0.6417; // Recombination factor from Aaron's talk.
271 
272  // Get dQ/dx YZ and X correction factors.
273  TFile* yzf = new TFile(yzfile.c_str());
274  TH2F* yzcorrposhist =(TH2F*)yzf->Get("correction_dqdx_ZvsY_positiveX_hist_2");
275  TH2F* yzcorrneghist =(TH2F*)yzf->Get("correction_dqdx_ZvsY_negativeX_hist_2");
276  TFile* xf = new TFile(xfile.c_str());
277  TH1F* xcorrhist = (TH1F*)xf->Get("dqdx_X_correction_hist_2");
278 
279  // Get the calorimetry objects from the event using the shower utilities.
280  std::vector<anab::Calorimetry> calovec =
282 
283  // Loop over all plane calorimetry objects, but only use the collection plane.
284  for(const anab::Calorimetry& calo : calovec) {
285  if(calo.PlaneID().Plane != 2) continue;
286 
287  // Loop over all hits in the collection plane calorimetry object.
288  for(unsigned i = 0; i < calo.dQdx().size(); ++i) {
289 
290  double dQdx = calo.dQdx()[i];
291  const double pitch = calo.TrkPitchVec()[i];
292  const geo::Point_t& pos = calo.XYZ()[i];
293  const double x = pos.X();
294  const double y = pos.Y();
295  const double z = pos.Z();
296  // Can't apply location-dependent corrections if there's no location available.
297  if(x==0 && y==0 && z==0) {
298  totE += dQdx*pitch*norm/calib*Wion/recob * 1e-3;
299  continue;
300  }
301  // Spatial corrections.
302  double yzcorr;
303  if(x >= 0) {
304  yzcorr = yzcorrposhist->GetBinContent(yzcorrposhist->FindBin(z,y));
305  } else {
306  yzcorr = yzcorrneghist->GetBinContent(yzcorrneghist->FindBin(z,y));
307  }
308  // Correct dQ/dx.
309  // std::cout << "Bare energy (GeV): " << dQdx*pitch*norm/calib*Wion/recob * 1e-3 << '\n';
310  const double xcorr = xcorrhist->GetBinContent(xcorrhist->FindBin(x));
311  // std::cout << "Hit energy (GeV): " << xcorr*yzcorr*dQdx*pitch*norm/calib*Wion/recob * 1e-3 << "\n\n";
312  totE += xcorr*yzcorr*dQdx*pitch*norm/calib*Wion/recob * 1e-3; // Convert from MeV to GeV.
313  } // for hits in calo
314  } // for calo objects
315 
316  // std::cout << "Total energy: " << totE << '\n';
317  return totE;
318 }
319 
320 } // namespace pizero
321 
322 #endif // SHOWERPROCESS_H
float Length(const PFPStruct &pfp)
Definition: PFPUtils.cxx:3303
const art::Event * m_evt
Definition: ShowerProcess.h:36
double energy(const std::string &caloLabel, const double calib, const double norm, const std::string &scefile, const std::string &yzfile, const std::string &xfile) const
Reconstruction base classes.
std::vector< const simb::MCParticle * > mcparticles() const
std::string string
Definition: nybbler.cc:12
std::vector< const recob::Shower * > showers() const
detinfo::DetectorClocksData const * m_clockdata
Definition: ShowerProcess.h:37
std::vector< anab::Calorimetry > GetRecoShowerCalorimetry(const recob::Shower &shower, art::Event const &evt, const std::string showerModule, const std::string caloModule) const
Get shower calo info.
std::vector< const recob::Track * > m_tracks
Definition: ShowerProcess.h:30
ShowerProcess(const simb::MCParticle &mcpart, const art::Event &evt, detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, std::string showerLabel="pandoraShower", std::string trackLabel="pandoraTrack", std::string simulationLabel="largeant")
Definition: ShowerProcess.h:55
std::string m_simulationLabel
Definition: ShowerProcess.h:41
Particle class.
int TrackId() const
Definition: MCParticle.h:210
std::vector< const simb::MCParticle * > m_mcparts
Definition: ShowerProcess.h:28
const simb::MCParticle * GetMCParticleFromReco(detinfo::DetectorClocksData const &clockData, const recob::PFParticle &pfpart, art::Event const &evt, std::string pfparticleModule) const
bool isRealData() const
T abs(T value)
ShowerProcess(const recob::Shower &shower, const art::Event &evt, detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, std::string showerLabel="pandoraShower", std::string trackLabel="pandoraTrack", std::string simulationLabel="largeant")
Definition: ShowerProcess.h:73
std::string m_showerLabel
Definition: ShowerProcess.h:39
const double e
Ionization at a point of the TPC sensitive volume.
Definition: SimChannel.h:84
std::vector< const recob::Track * > tracks() const
const double a
std::string m_trackLabel
Definition: ShowerProcess.h:40
Definition: Cone.h:19
ValidHandle< PROD > getValidHandle(InputTag const &tag) const
Definition: DataViewImpl.h:441
p
Definition: test.py:223
ShowerProcess(const simb::MCParticle &mcpart, const recob::Shower &shower, const art::Event &evt, detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, std::string showerLabel="pandoraShower", std::string trackLabel="pandoraTrack", std::string simulationLabel="largeant")
Definition: ShowerProcess.h:90
std::vector< std::pair< const recob::Shower *, double > > GetRecoShowerListFromMCParticle(detinfo::DetectorClocksData const &clockData, const simb::MCParticle &part, art::Event const &evt, std::string showerModule) const
protoana::ProtoDUNEShowerUtils shUtils
Definition: ShowerProcess.h:51
auto norm(Vector const &v)
Return norm of the specified vector.
detinfo::DetectorPropertiesData const * m_detprop
Definition: ShowerProcess.h:38
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:184
const Cone * cone() const
int ID() const
Definition: Track.h:198
std::vector< const recob::Shower * > m_showers
Definition: ShowerProcess.h:29
protoana::ProtoDUNETruthUtils truthUtils
Definition: ShowerProcess.h:50
Contains all timing reference information for the detector.
static bool * b
Definition: config.cpp:1043
const recob::Track * track() const
list x
Definition: train.py:276
std::vector< const sim::IDE * > HitToSimIDEs_Ps(detinfo::DetectorClocksData const &clockData, recob::Hit const &hit) const
TCEvent evt
Definition: DataStructs.cxx:7
double Wion
Definition: doAna.cpp:16
const simb::MCParticle * mcparticle() const
const recob::Shower * shower() const
Track from a non-cascading particle.A recob::Track consists of a recob::TrackTrajectory, plus additional members relevant for a "fitted" track:
Definition: Track.h:49
calorimetry