PiZeroProcess.h
Go to the documentation of this file.
1 #ifndef PIZERO_PROCESS_H
2 #define PIZERO_PROCESS_H
3 
4 #include <cmath>
5 #include <fstream>
6 #include <iostream>
7 #include <string>
8 #include <unordered_map>
9 #include <vector>
10 
11 #include "TTree.h"
12 
13 // Larsoft includes
22 
23 //#include "dune/Protodune/singlephase/DataUtils/ProtoDUNEShowerUtils.h"
26 
27 namespace pizero {
28 
29 // Function to find the closest distance between a line and a point.
30 inline double ClosestDistanceToPoint(const TVector3& p,
31  const TVector3& lineStart, const TVector3& lineDir) {
32  // Difference vector between line start and point.
33  const TVector3 diff = p - lineStart;
34  // Get line projection onto difference vector.
35  const TVector3 proj = lineDir * diff.Dot(lineDir) * (1.0 / lineDir.Mag2());
36  // The difference between the difference and projection vectors is
37  // called the rejection vector and returns the closest distance.
38  return (diff - proj).Mag();
39 }
40 
41 // Function to find the point in the middle of the shortest distance between two lines.
42 inline TVector3 ClosestPoint(const TVector3& a, const TVector3& adir,
43  const TVector3& b, const TVector3& bdir) {
44  TVector3 result(-99999., -99999., -99999.);
45  // Deal with both vectors being parallel.
46  if (adir != bdir) {
47  const TVector3 n1 = adir.Cross(bdir.Cross(adir));
48  const TVector3 n2 = bdir.Cross(adir.Cross(bdir));
49  const TVector3 c1 = a + adir * ((b - a).Dot(n2) / adir.Dot(n2));
50  const TVector3 c2 = b + bdir * ((a - b).Dot(n1) / bdir.Dot(n1));
51 
52  result = c1 + 0.5 * (c2 - c1);
53  }
54 
55  return result;
56 }
57 inline TVector3 ClosestPoint(const recob::Shower* showerA,
58  const recob::Shower* showerB) {
59  const TVector3 candidate =
60  ClosestPoint(showerA->ShowerStart(), showerA->Direction(),
61  showerB->ShowerStart(), showerB->Direction());
62 
63  return candidate;
64 }
65 
66 // Function to find the shortest distance between two lines.
67 inline double ClosestDistance(const TVector3& a, const TVector3& adir,
68  const TVector3& b, const TVector3& bdir) {
69  // Find unit vector perpendicular to both a and b.
70  const TVector3 unit = adir.Cross(bdir) * (1.0 / adir.Cross(bdir).Mag());
71  // Project difference vector on perpendicular vector.
72  return abs((a - b).Dot(unit));
73 }
74 inline double ClosestDistance(const recob::Shower* showerA,
75  const recob::Shower* showerB) {
76  // Check whether the intersection is behind both showers.
77  const TVector3 candidate =
78  ClosestPoint(showerA->ShowerStart(), showerA->Direction(),
79  showerB->ShowerStart(), showerB->Direction());
80  const TVector3 startPlusDirA = showerA->ShowerStart() + showerA->Direction();
81  const TVector3 startPlusDirB = showerB->ShowerStart() + showerB->Direction();
82  const TVector3 startMinusDirA = showerA->ShowerStart() - showerA->Direction();
83  const TVector3 startMinusDirB = showerB->ShowerStart() - showerB->Direction();
84  if((startPlusDirA-candidate).Mag() < (startMinusDirA-candidate).Mag() ||
85  (startPlusDirB-candidate).Mag() < (startMinusDirB-candidate).Mag()) {
86  return -1;
87  }
88 
89  return ClosestDistance(showerA->ShowerStart(), showerA->Direction(),
90  showerB->ShowerStart(), showerB->Direction());
91 }
92 
93 // Class to hold all relevant objects and information of a pi0 decay and
94 // reconstruction process.
96  private:
97  // Objects associated with the process.
98  std::unique_ptr<ShowerProcess> _shProcess1;
99  std::unique_ptr<ShowerProcess> _shProcess2;
100  // const recob::Shower* _shower1 = 0x0;
101  // const recob::Shower* _shower2 = 0x0;
102 
103  const simb::MCParticle* _pi0 = 0x0;
104  // const simb::MCParticle* _photon1 = 0x0;
105  // const simb::MCParticle* _photon2 = 0x0;
106 
107  const art::Event& _evt;
111 
112  // Utility objects.
115 
116  public:
117  PiZeroProcess(const simb::MCParticle& mcp, const art::Event& evt,
118  const detinfo::DetectorClocksData& clockData,
119  const detinfo::DetectorPropertiesData& detProp,
122  const detinfo::DetectorClocksData& clockData,
123  const detinfo::DetectorPropertiesData& detProp,
125  // PiZeroProcess(const recob::Shower& showerA, const recob::Shower& showerB,
126  // const art::Event& evt,
127  // std::string showerLabel);
129 
130  bool _haveMCInfo;
132 
133  // Reset function to start with a clean slate.
134  void reset();
135 
136  // Const access to private members.
137  const simb::MCParticle* pi0() const { return _pi0; }
138  const ShowerProcess* showerProcess1() const {
139  return &*_shProcess1;
140  }
141  const ShowerProcess* showerProcess2() const {
142  return &*_shProcess2;
143  }
144  const simb::MCParticle* photon1() const {
145  return _shProcess1? _shProcess1->mcparticle(): 0x0;
146  }
147  const simb::MCParticle* photon2() const {
148  return _shProcess2? _shProcess2->mcparticle(): 0x0;
149  }
150  const recob::Shower* shower1() const {
151  return _shProcess1? _shProcess1->shower(): 0x0;
152  }
153  const recob::Shower* shower2() const {
154  return _shProcess2? _shProcess2->shower(): 0x0;
155  }
156  const recob::Track* track1() const {
157  return _shProcess1? _shProcess1->track(): 0x0;
158  }
159  const recob::Track* track2() const {
160  return _shProcess2? _shProcess2->track(): 0x0;
161  }
162  const Cone* cone1() const {
163  return _shProcess1? _shProcess1->cone(): 0x0;
164  }
165  const Cone* cone2() const {
166  return _shProcess2? _shProcess2->cone(): 0x0;
167  }
168  const art::Event* evt() const { return &_evt; }
170 
171  // Functions to check whether data have been set (disallow partial reco).
172  bool allMCSet() const;
173  bool allRecoSet() const;
174 
175  // Function to set the pi0 and photons.
176  void setPi0(const simb::MCParticle& newPi0);
177 
178  // Function to create the branches for all variables in a TTree.
179  void createBranches(TTree* tree);
180 
181  // Function to fill MC info from the MCParticles.
182  void fillMCInfo();
183 
184  // Function to automatically fill shower info from the found showers.
185  void fillRecoInfo(calo::CalorimetryAlg caloAlg);
186 
187 }; // class PiZeroProcess
188 
189 
190 // Constructor to set internal data from an MCParticle.
192  const detinfo::DetectorClocksData& clockData,
193  const detinfo::DetectorPropertiesData& detProp,
195  _evt(evt), _clockData(clockData), _detProp{detProp}, _showerLabel(showerLabel)
196 {
197  if(mcp.PdgCode() == 111) {
198  // Got a pi0.
199  setPi0(mcp);
200  } else if(mcp.PdgCode() == 22) {
201  // Got a photon. Find the mother and run through the above process again.
202  if(mcp.Mother() == 0) return;
203  const simb::MCParticle* mcpmom = pi_serv->TrackIdToParticle_P(mcp.Mother());
204  if(mcpmom->PdgCode() == 111) setPi0(*mcpmom);
205  }
206 
207  // Quit if the system did not manage to find appropriate MCParticles.
208  if(!allMCSet()) return;
209 }
210 
211 // Constructor to set internal data from a shower.
213  const detinfo::DetectorClocksData& clockData,
214  const detinfo::DetectorPropertiesData& detProp,
216  _evt(evt), _clockData(clockData), _detProp{detProp}, _showerLabel(showerLabel)
217 {
218  // Get the event's showers.
219  auto showerHandle = _evt.getHandle<std::vector<recob::Shower> >(_showerLabel);
220  if (!showerHandle) return;
221  if(showerHandle->size() < 2) return;
222 
223  // For each shower, find the one which is closest to intersecting.
224  double min_dist = 100000;
225  const recob::Shower* shMatch = 0x0;
226  for(const recob::Shower& potMatch : *showerHandle) {
227  if(&potMatch == &shower) continue;
228 
229  const double this_dist = pizero::ClosestDistance(&shower, &potMatch);
230  if(this_dist < min_dist) {
231  min_dist = this_dist;
232  shMatch = &potMatch;
233  }
234  }
235  TVector3 reco_pi0_location = pizero::ClosestPoint(&shower, shMatch);
236 
237  // Find closest MC pi0 match to the reconstructed pi0 vertex.
238  double reco_mismatch = 100000;
239  const simb::MCParticle* min_pi0 = 0;
240  for(auto const& p : pi_serv->ParticleList()) {
241  const simb::MCParticle* true_pi0 = p.second;
242  // std::cout << "Particle PDG: " << true_pi0->PdgCode() << '\n';
243  if(true_pi0->PdgCode() != 111) continue;
244 
245  const double this_dist = (true_pi0->Position().Vect() - reco_pi0_location).Mag();
246  if(this_dist < reco_mismatch) {
247  reco_mismatch = this_dist;
248  min_pi0 = true_pi0;
249  }
250  }
251  if(min_pi0 == 0) return;
252 
253  // Fill internal data fields with the found pointers.
254  setPi0(*min_pi0);
255  // Check whether we have all necessary pointers.
256  if(!allMCSet()) {
257  _pi0 = 0x0;
258  _shProcess1 = 0x0;
259  _shProcess2 = 0x0;
260  // _photon1 = 0x0;
261  // _photon2 = 0x0;
262  // _shower1 = 0x0;
263  // _shower2 = 0x0;
264  return;
265  }
266  // // Use truth utilities to see which shower matches the first photon best.
267  // for(auto const& p : truthUtils.GetRecoShowerListFromMCParticle(*_photon1, _evt, _showerLabel)) {
268  // if(p.first->Length() - shower.Length() < 1e-5) {
269  // _shower1 = &shower;
270  // _shower2 = shMatch;
271  // break;
272  // } else if(p.first->Length() - shMatch->Length() < 1e-5) {
273  // _shower1 = shMatch;
274  // _shower2 = &shower;
275  // break;
276  // }
277  // }
278 }
279 
280 // Functions to check whether data have been set (disallow partial reco).
282  return (pi0() != 0x0) && (photon1() != 0x0) && (photon2() != 0x0);
283 }
285  return (shower1() != 0x0) && (shower2() != 0x0);
286 }
287 
288 // Function to set the pi0 and photons.
290  _pi0 = &newPi0;
291  if (_pi0->NumberDaughters() == 2) { // Skip rare decays for now.
292  // Find the associated photons through particle inventory.
295  // Set photon1 to be the more energetic one.
296  if(photon1->E() < photon2->E()) std::swap(photon1, photon2);
297  // Fill the showerProcesses.
298  _shProcess1 = std::make_unique<ShowerProcess>(*photon1, _evt, _clockData, _detProp);
299  _shProcess2 = std::make_unique<ShowerProcess>(*photon2, _evt, _clockData, _detProp);
300  }
301 }
302 
303 std::vector<PiZeroProcess> findPiZeros(const art::Event& evt,
304  std::string showerLabel = "pandoraShower", std::string trackLabel = "pandoraTrack") {
305  std::vector<PiZeroProcess> result;
306 
307  // Get the event's showers.
308  auto showerHandle = evt.getHandle<std::vector<recob::Shower>>(showerLabel);
309  if (!showerHandle || showerHandle->size() < 2) return result;
310 
311  // Find showers close to each other.
312  double showerDistThreshold = 50; // 50 cm is too far.
313  std::vector<std::pair<const recob::Shower*, const recob::Shower*>> showerPairs;
314  for(unsigned si = 0; si < showerHandle->size()-1; ++si) {
315  for(unsigned ssi = si+1; ssi < showerHandle->size(); ++ssi) {
316  const recob::Shower* shower1 = &showerHandle->at(si);
317  const recob::Shower* shower2 = &showerHandle->at(ssi);
318  if((shower1->ShowerStart() - shower2->ShowerStart()).Mag() < showerDistThreshold) {
319  showerPairs.push_back(std::make_pair(shower1, shower2));
320  }
321  }
322  }
323  std::cout << showerPairs.size() << " shower pairs.\n";
324 
325  // Of shower pairs in vicinity of each other, find those that point to a single vertex.
326 
327  // TODO: Finish this function. Place outside of class to make vector of all pizero candidates?
328 
329  return result;
330 }
331 
332 } // namespace pizero
333 
334 #endif
double E(const int i=0) const
Definition: MCParticle.h:233
const TVector3 & ShowerStart() const
Definition: Shower.h:192
const TLorentzVector & Position(const int i=0) const
Definition: MCParticle.h:219
int PdgCode() const
Definition: MCParticle.h:212
std::vector< PiZeroProcess > findPiZeros(const art::Event &evt, std::string showerLabel="pandoraShower", std::string trackLabel="pandoraTrack")
TVector3 ClosestPoint(const TVector3 &a, const TVector3 &adir, const TVector3 &b, const TVector3 &bdir)
Definition: PiZeroProcess.h:42
static QCString result
const art::Event * evt() const
const detinfo::DetectorPropertiesData & _detProp
Handle< PROD > getHandle(SelectorBase const &) const
Definition: DataViewImpl.h:382
std::string string
Definition: nybbler.cc:12
const recob::Track * track2() const
const simb::MCParticle * TrackIdToParticle_P(int id) const
const std::string _showerLabel
const detinfo::DetectorClocksData & _clockData
const recob::Track * track1() const
std::unique_ptr< ShowerProcess > _shProcess1
Definition: PiZeroProcess.h:98
const art::Event & _evt
bool allRecoSet() const
Particle class.
int NumberDaughters() const
Definition: MCParticle.h:217
art framework interface to geometry description
int Daughter(const int i) const
Definition: MCParticle.cxx:112
void fillRecoInfo(calo::CalorimetryAlg caloAlg)
const recob::Shower * shower2() const
T abs(T value)
const simb::MCParticle * photon1() const
bool allMCSet() const
const simb::MCParticle * pi0() const
void swap(Handle< T > &a, Handle< T > &b)
void setPi0(const simb::MCParticle &newPi0)
const double a
double ClosestDistanceToPoint(const TVector3 &p, const TVector3 &lineStart, const TVector3 &lineDir)
Definition: PiZeroProcess.h:30
Definition: Cone.h:19
p
Definition: test.py:223
const ShowerProcess * showerProcess1() const
const TVector3 & Direction() const
Definition: Shower.h:189
art::ServiceHandle< cheat::ParticleInventoryService > pi_serv
Definition of data types for geometry description.
const sim::ParticleList & ParticleList() const
const Cone * cone1() const
const recob::Shower * shower1() const
Declaration of signal hit object.
const simb::MCParticle * _pi0
const simb::MCParticle * photon2() const
double ClosestDistance(const TVector3 &a, const TVector3 &adir, const TVector3 &b, const TVector3 &bdir)
Definition: PiZeroProcess.h:67
Contains all timing reference information for the detector.
void createBranches(TTree *tree)
static bool * b
Definition: config.cpp:1043
std::unique_ptr< ShowerProcess > _shProcess2
Definition: PiZeroProcess.h:99
Access the description of detector geometry.
protoana::ProtoDUNETruthUtils truthUtils
const Cone * cone2() const
PiZeroProcess(const simb::MCParticle &mcp, const art::Event &evt, const detinfo::DetectorClocksData &clockData, const detinfo::DetectorPropertiesData &detProp, std::string showerLabel)
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
std::string showerLabel() const
const ShowerProcess * showerProcess2() const