BackTrackerCore.h
Go to the documentation of this file.
1 //
2 // BackTrackerCore.h
3 //
4 // Created by Brian Rebel on 3/13/17.
5 // Modified by Leo Bellantoni, Feb-Mar 2020
6 //
7 //
8 /// Code to link reconstructed objects back to the MC truth information
9 
10 
11 
12 #ifndef GAR_CHEAT_BackTrackerCore_h
13 #define GAR_CHEAT_BackTrackerCore_h
14 
15 
16 
18 
20 #include "nug4/ParticleNavigation/ParticleList.h"
21 #include "nug4/ParticleNavigation/EveIdCalculator.h"
23 
34 #include "Geometry/GeometryGAr.h"
35 
36 #include <unordered_map>
37 
38 
39 
40 namespace sim {
41  class ParticleList;
42  class EveIdCalculator;
43 }
44 
45 
46 
47 namespace gar{
48  namespace cheat{
49 
50 
51 
52  // Two helper classes structs for doing backtracking analyses
53  struct HitIDE {
54  int trackID; ///< Geant4 trackID, as modified by ParticleListAction::PreTrackingAction
55  float energyFrac; ///< fraction of gar::rec::Hit energy from the particle with this trackID
56  float energyTot; ///< total energy for this trackID. In units of probably-GeV.
57  TLorentzVector position; ///< deposited energy-weighted mean true 4-position [cm,ns]
58  TLorentzVector momentum; ///< deposited energy-weighted mean true 4-momentum [GeV/c,GeV]
59 
60  HitIDE() {}
61 
62  HitIDE(int id, float ef, float e, const TLorentzVector& pos, const TLorentzVector& mom)
63  : trackID(id), energyFrac(ef), energyTot(e), position(pos), momentum(mom) {}
64 
65  bool operator == (HitIDE const& hitr) const {
66  if(this->trackID != hitr.trackID) return false;
67  if(this->energyTot != hitr.energyTot) return false;
68  if(this->energyFrac != hitr.energyFrac) return false;
69  if(this->position != hitr.position) return false;
70  if(this->momentum != hitr.momentum) return false;
71  return true;
72  }
73 
74  // sort in this order: trackID, time, total then frac deposited energy, postion, momentum, energy
75  // this is probably overkill, but better to be careful
76  bool operator < (HitIDE const& hitr) const {
77  if(*this == hitr) return false;
78  if(this->trackID < hitr.trackID) return true;
79  if(this->trackID > hitr.trackID) return false;
80  if(this->energyTot < hitr.energyTot) return true;
81  if(this->energyTot > hitr.energyTot) return false;
82  if(this->energyFrac < hitr.energyFrac) return true;
83  if(this->energyFrac > hitr.energyFrac) return false;
84  if(this->position.Rho() < hitr.position.Rho()) return true;
85  if(this->position.Rho() > hitr.position.Rho()) return false;
86  if(this->position.Phi() < hitr.position.Phi()) return true;
87  if(this->position.Phi() > hitr.position.Phi()) return false;
88  if(this->position.Z() < hitr.position.Z()) return true;
89  if(this->position.Z() > hitr.position.Z()) return false;
90  if(this->momentum.P() < hitr.position.P()) return true;
91  if(this->momentum.P() > hitr.position.P()) return false;
92  if(this->momentum.E() < hitr.position.E()) return true;
93  if(this->momentum.E() > hitr.position.E()) return false;
94  return false;
95 
96  }
97  };
98  struct CalIDE {
99  int trackID; ///< Geant4 trackID, as modified by ParticleListAction::PreTrackingAction
100  float energyFrac; ///< fraction of gar::rec::CaloHit energy from particle with this trackID
101  float energyTot; ///< total energy for this trackID. In units of probably-GeV.
102 
103  CalIDE() {}
104 
105  CalIDE(int id, float ef, float e)
106  : trackID(id), energyFrac(ef), energyTot(e) {}
107  };
108 
109 
110 
112  public:
113 
114  explicit BackTrackerCore(fhicl::ParameterSet const& pset);
115  ~BackTrackerCore();
116 
117  // Set the EveIdCalculator for the owned ParticleList
118  void AdoptEveIdCalculator(sim::EveIdCalculator* ec) {
119  fParticleList.AdoptEveIdCalculator(ec);
120  }
121 
122  // Getter functions for users re. what back-trackable info is available in this event.
123  bool HasMC() {return fHasMC; }
124  bool HasHits() {return fHasHits; }
125  bool HasCalHits() {return fHasCalHits; }
126  bool HasTracks() {return fHasTracks; }
127  bool HasClusters() {return fHasClusters;}
128 
129 
130 
131 
132 
133  // Following should work as long as there are MCParticles and MCTruth
134  // data products in the event, and suitable Assns between them
135 
136  // ParticleList has no copy constructor. It does have iterators etc.
137  sim::ParticleList* GetParticleList() {
138  return &fParticleList;
139  }
140 
141  // Returns a bare pointer to the MCParticle corresponding to a given TrackID
142  // Negative trackID values, corresponding to EM shower particles, return
143  // the parent particle.
144  simb::MCParticle* TrackIDToParticle(int const& id) const;
145 
147  // Always walk up the ParticleList in case someday somebody changes it
148  return TrackIDToParticle(p->Mother());
149  }
150 
151  simb::MCParticle* FindEve(simb::MCParticle* const p) const;
152 
153  // FindTPCEve is not a const method because it saves result of previous
154  // calls in `this' for efficiency. 2nd signature mostly for internal use.
155  simb::MCParticle* FindTPCEve(simb::MCParticle* const p) const;
156  simb::MCParticle* FindTPCEve(int const trackId) const;
157 
158  bool IsForebearOf(simb::MCParticle* const forebear,
159  simb::MCParticle* const afterbear) const;
160 
161  // Returns an ::art::Ptr<> to simb::MCTruth
162  art::Ptr<simb::MCTruth> const ParticleToMCTruth(simb::MCParticle* const p) const;
163 
164  // Following should work as long as there are also RawDigit and EnergyDeposit
165  // data products in the event, and suitable Assns between them
166 
167  // These methods will return HitIDE structures containing the Geant4 track IDs of
168  // the particles contributing ionization electrons to the input hit
169  std::vector<HitIDE> HitToHitIDEs(art::Ptr<rec::Hit> const& hit) const;
170  std::vector<HitIDE> HitToHitIDEs( rec::Hit const& hit) const;
171 
172  std::vector<art::Ptr<rec::Hit>>
173  ParticleToHits(simb::MCParticle* const p,
174  std::vector<art::Ptr<rec::Hit>> const& allhits,
175  bool checkNeutrals=false) const;
176 
177  // Find the fraction of hits in a collection that come from the specified MCParticle
178  // with statistical uncertainty. Binomial uncertainty in weighted events is from
179  // the usual primitive algorithm, which is not obviously right to me.
180  std::pair<double,double>
181  HitPurity(simb::MCParticle* const p,
182  std::vector<art::Ptr<rec::Hit>> const& hits,
183  bool weightByCharge=false) const;
184 
185  // method to return the fraction of all hits in an event from a specific set of
186  // Geant4 track IDs that arerepresented in a collection of hits
187  std::pair<double,double>
188  HitEfficiency(simb::MCParticle* const p,
189  std::vector<art::Ptr<rec::Hit> > const& hits,
190  std::vector<art::Ptr<rec::Hit> > const& allhits,
191  bool weightByCharge=false) const;
192 
193 
194 
195 
196 
197  // Following should work as long as there are CaloRawDigit and CaloDeposit
198  // data products in the event, and suitable Assns between them
199 
200  // These methods will return HitIDE structures containing the Geant4 track IDs of
201  // the TPC-originating particles contributing ionization electrons to the input hit.
202  std::vector<CalIDE> CaloHitToCalIDEs(art::Ptr<rec::CaloHit> const& hit) const;
203  std::vector<CalIDE> CaloHitToCalIDEs( rec::CaloHit const& hit) const;
204 
205  std::vector<art::Ptr<rec::CaloHit>>
206  ParticleToCaloHits(simb::MCParticle* const p,
207  std::vector<art::Ptr<rec::CaloHit>> const& allhits) const;
208 
209  // Find the fraction of CaloHits in a collection that come from the specified
210  // MCParticle with statistical uncertainty. Binomial uncertainty in weighted
211  // events is from the usual primitive algorithm, which is not obviously right to me.
212  std::pair<double,double>
213  CaloHitPurity(simb::MCParticle* const p,
214  std::vector<art::Ptr<rec::CaloHit>> const& hits,
215  bool weightByCharge=false) const;
216 
217  // method to return the fraction of all hits in an event from a specific set of
218  // Geant4 track IDs that arerepresented in a collection of hits
219  std::pair<double,double>
220  CaloHitEfficiency(simb::MCParticle* const p,
221  std::vector<art::Ptr<rec::CaloHit>> const& hits,
222  std::vector<art::Ptr<rec::CaloHit>> const& allhits,
223  bool weightByCharge=false) const;
224 
225 
226 
227 
228 
229  // Following should work as long as there are reconstructed Track and Hit
230  // data products in the event, and suitable Assns between them
231  std::vector<art::Ptr<rec::Hit>> const TrackToHits(rec::Track* const t);
232 
233  std::vector<art::Ptr<rec::Hit>> const TPCClusterToHits(rec::TPCCluster* const clust);
234 
235  //std::vector<art::Ptr<rec::TPCCluster>> const TrackToClusters(rec::Track* const t);
236  std::vector<const rec::TPCCluster*> const TrackToClusters(rec::Track* const t);
237 
238  std::vector<std::pair<simb::MCParticle*,float>> TrackToMCParticles(rec::Track* const t);
239 
240  // given a pointer to a track object, returns the total true deposited energy [GeV]
241  // associated with the track
242  double TrackToTotalEnergy(rec::Track* const t);
243 
244  std::vector<art::Ptr<rec::Track>>
245  MCParticleToTracks(simb::MCParticle* const p,
247 
248 
249 
250 
251 
252  // Following should work as long as there are reconstructed Cluster and CaloHit
253  // data products in the event, and suitable Assns between them
254  std::vector<art::Ptr<rec::CaloHit>> const ClusterToCaloHits(rec::Cluster* const c);
255 
256  std::vector<std::pair<simb::MCParticle*,float>> ClusterToMCParticles(rec::Cluster* const c);
257 
258  std::vector<art::Ptr<rec::Cluster>>
259  MCParticleToClusters(simb::MCParticle* const p,
260  std::vector<art::Ptr<rec::Cluster>> const& clusters);
261 
262  bool ClusterCreatedMCParticle(simb::MCParticle* const p,
263  rec::Cluster* const c);
264 
265  bool MCParticleCreatedCluster(simb::MCParticle* const p,
266  rec::Cluster* const c);
267 
268 
269  private:
270  std::vector<HitIDE>
271  ChannelToHitIDEs(raw::Channel_t const& channel,
272  double const start, double const stop) const;
273 
274  std::vector<CalIDE>
275  CellIDToCalIDEs(raw::CellID_t const& cellID, float const time) const;
276 
277  std::vector<simb::MCParticle*>
278  MCPartsInCluster(rec::Cluster* const c);
279 
280  TLorentzVector EnergyDepositToMomentum(const int& trackID, const TLorentzVector& position, size_t& startTrajIndex) const;
281 
282 
283  protected:
284  bool fHasMC, fHasHits, fHasCalHits, fHasTracks, fHasClusters;
285  int fSTFU;
286 
287  const detinfo::DetectorClocks* fClocks; ///< Detector clock information
288  const geo::GeometryCore* fGeo; ///< pointer to the geometry
289 
290  bool fDisableRebuild; ///< for switching off backtracker's rebuild of the MCParticle tables
291  std::string fG4ModuleLabel; ///< label for geant4 module
292  std::string fRawTPCDataLabel; ///< label for TPC readout module
293  std::string fRawCaloDataLabel; ///< label for ECAL readout module
294  std::string fRawCaloDataECALInstance; ///< instance name for the ECAL raw hits
295  double fECALtimeResolution; ///< time resolution for hits in ECAL, nsec.
296  double fMinHitEnergyFraction; ///< min frac of ionization a track has to count in a TPC hit
297  double fMinCaloHitEnergyFrac; ///< min frac of ionization a track has to count in a CaloHit
298  std::string fTrackLabel; ///< label for final track producing module
299  std::string fTPCClusterLabel; ///< label for TPCCluster producing module
300  double fTrackFracMCP; ///< min frac of ionization in a track for matching to an MCParticle
301  std::string fClusterLabel; ///< label for ECAL cluster producing module
302  std::string fClusterECALInstance; ///< instance name for the ECAL clusters
303  double fClusterFracMCP; ///< min frac of ionization in a cluster for matching to an MCParticle
304 
305  sim::ParticleList fParticleList; ///< Maps MCParticle::TrackId() to same MCParticle
306  std::vector<art::Ptr<simb::MCTruth>> fMCTruthList; ///< all the MCTruths for the event
307  std::unordered_map<int, int> fTrackIDToMCTruthIndex; ///< map of track ids to MCTruthList entry. Track Ids from MCParticle
308  ///< table in event store (no track ID <0)
309  std::unordered_map<int, int>* fECALTrackToTPCTrack; ///< results of previous FindTPCEve calls
310 
311  double fInverseVelocity; ///< inverse drift velocity
312  double fLongDiffConst; ///< longitudinal diffusion constant
313  bool fSplitEDeps; ///< use weights from PRFs to break true energy deposits into channel specific contributions
314 
315  // vector gives a fast lookup and is only 677864*24 = 16Mbytes.
316  std::vector<std::vector<std::pair<const sdp::EnergyDeposit*, float const>>> fChannelToEDepCol; ///< convenience collections of EnergyDeposits for each channel
317 
318  // ECAL max channel id is something like 2^56. Try an unordered map, not a vector.
319  std::unordered_map<raw::CellID_t,std::vector<const sdp::CaloDeposit*>>
320  fCellIDToEDepCol; ///< convenience collections of EnergyDeposit for each cell
321 
322  // Mapping final reco products to their constituents
323  std::unordered_map< rec::IDNumber, std::vector<art::Ptr<rec::Hit>> >
324  fTrackIDToHits; ///< Reco track ID to track's hits
325  // Mapping final reco products to their constituents
326  //std::unordered_map< rec::IDNumber, std::vector<art::Ptr<rec::TPCCluster>> >
327  std::unordered_map< rec::IDNumber, std::vector<const rec::TPCCluster*> >
328  fTrackIDToClusters; ///< Reco track ID to track's clusters
329 
330 
331  // Mapping final reco products to their constituents
332  std::unordered_map< rec::IDNumber, std::vector<art::Ptr<rec::Hit>> >
333  fTPCClusterIDToHits; ///< Reco TPC cluster ID to cluster's hits
334 
335  std::unordered_map< rec::IDNumber, std::vector<art::Ptr<rec::CaloHit>> >
336  fClusterIDToCaloHits; ///< Reco ECAL cluster ID to CaloHits
337 
338  };
339  } // namespace
340 }
341 
342 
343 #endif /* GAR_CHEAT_BackTrackerCore_h */
float energyFrac
fraction of gar::rec::Hit energy from the particle with this trackID
TLorentzVector position
deposited energy-weighted mean true 4-position [cm,ns]
double fClusterFracMCP
min frac of ionization in a cluster for matching to an MCParticle
double fLongDiffConst
longitudinal diffusion constant
std::vector< std::vector< std::pair< const sdp::EnergyDeposit *, float const > > > fChannelToEDepCol
convenience collections of EnergyDeposits for each channel
HitIDE(int id, float ef, float e, const TLorentzVector &pos, const TLorentzVector &mom)
std::unordered_map< rec::IDNumber, std::vector< const rec::TPCCluster * > > fTrackIDToClusters
Reco track ID to track&#39;s clusters.
std::string string
Definition: nybbler.cc:12
int Mother() const
Definition: MCParticle.h:213
const detinfo::DetectorClocks * fClocks
Detector clock information.
struct vector vector
TLorentzVector momentum
deposited energy-weighted mean true 4-momentum [GeV/c,GeV]
double fMinHitEnergyFraction
min frac of ionization a track has to count in a TPC hit
std::string fRawCaloDataECALInstance
instance name for the ECAL raw hits
Description of geometry of one entire detector.
Definition: GeometryCore.h:436
std::string fClusterLabel
label for ECAL cluster producing module
uint8_t channel
Definition: CRTFragment.hh:201
std::unordered_map< raw::CellID_t, std::vector< const sdp::CaloDeposit * > > fCellIDToEDepCol
convenience collections of EnergyDeposit for each cell
Particle class.
const geo::GeometryCore * fGeo
pointer to the geometry
void AdoptEveIdCalculator(sim::EveIdCalculator *ec)
std::unordered_map< int, int > fTrackIDToMCTruthIndex
double fTrackFracMCP
min frac of ionization in a track for matching to an MCParticle
std::unordered_map< rec::IDNumber, std::vector< art::Ptr< rec::Hit > > > fTrackIDToHits
Reco track ID to track&#39;s hits.
float energyFrac
fraction of gar::rec::CaloHit energy from particle with this trackID
std::string fClusterECALInstance
instance name for the ECAL clusters
const double e
std::string fRawTPCDataLabel
label for TPC readout module
float energyTot
total energy for this trackID. In units of probably-GeV.
uint32_t Channel_t
Definition: RawDigit.h:35
sim::ParticleList fParticleList
Maps MCParticle::TrackId() to same MCParticle.
std::string fTPCClusterLabel
label for TPCCluster producing module
simb::MCParticle * FindMother(simb::MCParticle *const p) const
std::string fTrackLabel
label for final track producing module
p
Definition: test.py:223
std::unordered_map< rec::IDNumber, std::vector< art::Ptr< rec::Hit > > > fTPCClusterIDToHits
Reco TPC cluster ID to cluster&#39;s hits.
std::unordered_map< rec::IDNumber, std::vector< art::Ptr< rec::CaloHit > > > fClusterIDToCaloHits
Reco ECAL cluster ID to CaloHits.
Definition of basic calo raw digits.
sim::ParticleList * GetParticleList()
std::unordered_map< int, int > * fECALTrackToTPCTrack
results of previous FindTPCEve calls
long long int CellID_t
Definition: CaloRawDigit.h:24
CalIDE(int id, float ef, float e)
Code to link reconstructed objects back to the MC truth information.
Detector simulation of raw signals on wires.
std::string fG4ModuleLabel
label for geant4 module
Definition: tracks.py:1
General GArSoft Utilities.
int trackID
Geant4 trackID, as modified by ParticleListAction::PreTrackingAction.
int trackID
Geant4 trackID, as modified by ParticleListAction::PreTrackingAction.
code to link reconstructed objects back to the MC truth information
Definition: BackTracker.cc:22
bool fSplitEDeps
use weights from PRFs to break true energy deposits into channel specific contributions ...
std::string fRawCaloDataLabel
label for ECAL readout module
float energyTot
total energy for this trackID. In units of probably-GeV.
std::vector< art::Ptr< simb::MCTruth > > fMCTruthList
all the MCTruths for the event
double fECALtimeResolution
time resolution for hits in ECAL, nsec.
art framework interface to geometry description
double fInverseVelocity
inverse drift velocity
bool fDisableRebuild
for switching off backtracker&#39;s rebuild of the MCParticle tables
double fMinCaloHitEnergyFrac
min frac of ionization a track has to count in a CaloHit
bool operator<(const BeamGateInfo &lhs, const BeamGateInfo &rhs)
Definition: BeamGateInfo.h:45
TFile * ef
Definition: doAna.cpp:25
bool operator==(ModuleKeyAndType const &a, ModuleKeyAndType const &b) noexcept