LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
OpticalRecoAna_module.cc
Go to the documentation of this file.
1 //Analyzer for flash<--->track matching (testing against MC)
2 
3 #include <string>
4 #include <vector>
5 
6 // Framework includes
12 #include "art_root_io/TFileService.h"
14 #include "fhiclcpp/ParameterSet.h"
16 
17 // LArSoft includes
24 
25 #include "TH1.h"
26 #include "TTree.h"
27 
28 namespace opreco {
29 
30  //bookkeeping on all the matches
31  struct flash_match {
32  std::vector<size_t> particle_indices;
33  std::vector<size_t> track_indices;
34  };
35  struct track_match {
36  std::vector<size_t> particle_indices;
37  std::vector<size_t> flash_indices;
38  };
39  struct particle_match {
40  std::vector<size_t> flash_indices;
41  std::vector<size_t> track_indices;
42  };
43 
45  public:
47 
48  void beginJob();
49  void analyze(const art::Event&);
50 
51  private:
52  //fcl parameters here
53  std::string fFlashModuleLabel;
54  std::string fTrackModuleLabel;
56  float fPEMin;
58 
59  std::vector<flash_match> fFlash_match_vector;
60  std::vector<track_match> fTrack_match_vector;
61  std::vector<particle_match> fParticle_match_vector;
62 
63  void get_MC_particle_list(sim::ParticleList const&, std::vector<simb::MCParticle>&);
64  simb::Origin_t get_MC_particle_origin(simb::MCParticle const&);
65  float update_MC_particle_time(simb::MCParticle const&, bool&, geo::Geometry const&);
66 
67  //matching functions
68  void match_flashes_to_tracks(std::vector<recob::OpFlash> const&,
69  std::vector<recob::Track> const&);
70 
71  void match_flashes_to_particles(std::vector<recob::OpFlash> const&,
72  std::vector<simb::MCParticle> const&,
73  float const&,
74  geo::Geometry const&);
75 
76  TH1F* fTimeDiff;
79 
80  TTree* fMatchTree_PF;
82  int fRun;
83  int fEvent;
88  float fParticleVx;
89  float fParticleVy;
90  float fParticleVz;
91  int fFlashID;
92  float fFlashTime;
94  float fFlashY;
95  float fFlashZ;
96  float fFlashYWidth;
97  float fFlashZWidth;
98  float fFlashPE;
102  };
103 
104 }
105 
106 namespace opreco {
108 }
109 
110 // Constructor
112 {
113 
114  // Indicate that the Input Module comes from .fcl
115  fFlashModuleLabel = pset.get<std::string>("FlashModule");
116  fTrackModuleLabel = pset.get<std::string>("TrackModule");
117  fKineticEnergyMin = pset.get<float>("KineticEnergyMin");
118  fPEMin = pset.get<float>("PEMin");
119  fTimeMatchMax = pset.get<float>("TimeMatchMax");
120 
121  fFlash_match_vector.clear();
122  fTrack_match_vector.clear();
123  fParticle_match_vector.clear();
124 }
125 
126 // Do something here to setup the file (like make a TTree)
128 {
130  fTimeDiff = tfs->make<TH1F>(
131  "htdiff",
132  "Time difference between particles and flashes; t_diff (ns); flash/particle pairs",
133  1e3,
134  -5e6,
135  5e6);
136  fTimeDiff_fine = tfs->make<TH1F>(
137  "htdiff_fine",
138  "Time difference between particles and flashes; t_diff (ns); flash/particle pairs",
139  100,
140  -1000,
141  1000);
142  fNBeamFlashes = tfs->make<TH1I>(
143  "hNBeamFlashes", "Number of flashes OnBeamTime per event; N_{Flashes}; Events", 5, 0, 5);
144 
145  fMatchTree_PF = tfs->make<TTree>("MatchTree_PF", "MatchTree_PF");
146  fMatchTree_PF->Branch("Run", &fRun, "Run/I");
147  fMatchTree_PF->Branch("Event", &fEvent, "Event/I");
148  fMatchTree_PF->Branch("p_id", &fParticleID, "p_id/I");
149  fMatchTree_PF->Branch("p_time", &fParticleTime, "p_time/F");
150  fMatchTree_PF->Branch("p_vx", &fParticleVx, "p_vx/F");
151  fMatchTree_PF->Branch("p_vy", &fParticleVy, "p_vy/F");
152  fMatchTree_PF->Branch("p_vz", &fParticleVz, "p_vz/F");
153  fMatchTree_PF->Branch("p_mid", &fParticleMother, "p_mid/I");
154  fMatchTree_PF->Branch("p_trackid", &fParticleTrackID, "p_trackid/I");
155  fMatchTree_PF->Branch("FlashID", &fFlashID, "flash_id/I");
156  fMatchTree_PF->Branch("f_time", &fFlashTime, "f_time/F");
157  fMatchTree_PF->Branch("f_timewidth", &fFlashTimeWidth, "f_timewidth/F");
158  fMatchTree_PF->Branch("f_y", &fFlashY, "f_y/F");
159  fMatchTree_PF->Branch("f_z", &fFlashZ, "f_z/F");
160  fMatchTree_PF->Branch("f_ywidth", &fFlashYWidth, "f_ywidth/F");
161  fMatchTree_PF->Branch("f_zwidth", &fFlashYWidth, "f_zwidth/F");
162  fMatchTree_PF->Branch("f_onbeamtime", &fFlashOnBeamTime, "f_onbeamtime/I");
163  fMatchTree_PF->Branch("f_pe", &fFlashPE, "f_pe/F");
164  fMatchTree_PF->Branch("matchIndex", &fMatchIndex, "matchIndex/I");
165 
166  fMatchTree_PF_NotNu = tfs->make<TTree>("MatchTree_PF_NotNu", "MatchTree_PF_NotNu");
167  fMatchTree_PF_NotNu->Branch("Run", &fRun, "Run/I");
168  fMatchTree_PF_NotNu->Branch("Event", &fEvent, "Event/I");
169  fMatchTree_PF_NotNu->Branch("p_id", &fParticleID, "p_id/I");
170  fMatchTree_PF_NotNu->Branch("p_time", &fParticleTime, "p_time/F");
171  fMatchTree_PF_NotNu->Branch("p_vx", &fParticleVx, "p_vx/F");
172  fMatchTree_PF_NotNu->Branch("p_vy", &fParticleVy, "p_vy/F");
173  fMatchTree_PF_NotNu->Branch("p_vz", &fParticleVz, "p_vz/F");
174  fMatchTree_PF_NotNu->Branch("p_mid", &fParticleMother, "p_mid/I");
175  fMatchTree_PF_NotNu->Branch("p_trackid", &fParticleTrackID, "p_trackid/I");
176  fMatchTree_PF_NotNu->Branch("FlashID", &fFlashID, "flash_id/I");
177  fMatchTree_PF_NotNu->Branch("f_time", &fFlashTime, "f_time/F");
178  fMatchTree_PF_NotNu->Branch("f_timewidth", &fFlashTimeWidth, "f_timewidth/F");
179  fMatchTree_PF_NotNu->Branch("f_y", &fFlashY, "f_y/F");
180  fMatchTree_PF_NotNu->Branch("f_z", &fFlashZ, "f_z/F");
181  fMatchTree_PF_NotNu->Branch("f_ywidth", &fFlashYWidth, "f_ywidth/F");
182  fMatchTree_PF_NotNu->Branch("f_zwidth", &fFlashYWidth, "f_zwidth/F");
183  fMatchTree_PF_NotNu->Branch("f_onbeamtime", &fFlashOnBeamTime, "f_onbeamtime/I");
184  fMatchTree_PF_NotNu->Branch("f_pe", &fFlashPE, "f_pe/F");
185  fMatchTree_PF_NotNu->Branch("matchIndex", &fMatchIndex_NotNu, "matchIndex/I");
186 }
187 
188 // The analyzer itself
190 {
191 
192  //get flag for MC
193  const bool is_MC = !(evt.isRealData());
194 
195  fRun = evt.id().run();
196  fEvent = evt.id().event();
197 
198  //first get out track, flash, and particle list handles
200  evt.getByLabel(fFlashModuleLabel, flash_handle);
201  std::vector<recob::OpFlash> const& flash_vector(*flash_handle);
202  fFlash_match_vector.resize(flash_vector.size());
203 
204  MF_LOG_INFO("OpticalRecoAna") << "Number of flashes is " << flash_vector.size() << std::flush;
205 
206  //all this for the MC matching
207  if (is_MC) {
208 
210  std::vector<simb::MCParticle> particle_list;
211  get_MC_particle_list(pi_serv->ParticleList(), particle_list);
212  fParticle_match_vector.resize(particle_list.size());
213 
214  mf::LogInfo("OpticalRecoAna") << "Number of MC particles is " << particle_list.size();
215 
217  const float ns_per_PMT_tick =
218  1e3; // already converted to microseconds//( 1e3 / odp->SampleFreq()) ; //SampleFreq is in MHz
220 
221  match_flashes_to_particles(flash_vector, particle_list, ns_per_PMT_tick, *geometry_handle);
222  int n_flashes = 0;
223  for (auto const& my_flash : flash_vector) {
224  if (my_flash.OnBeamTime() == 1) n_flashes++;
225  }
226  fNBeamFlashes->Fill(n_flashes);
227  }
228 }
229 
231 {
233  return (pi_serv->TrackIdToMCTruth_P(particle.TrackId()))->Origin();
234 }
235 
237  std::vector<simb::MCParticle>& particle_vector)
238 {
239 
240  for (sim::ParticleList::const_iterator ipart = plist.begin(); ipart != plist.end(); ++ipart) {
241 
242  const simb::MCParticle* particle = (*ipart).second;
243  //do not store if it's below our energy cut
244  if (particle->E() < 0.001 * particle->Mass() + fKineticEnergyMin) continue;
245 
246  //check to see if it's a charged particle we expect to leave ionization
247  const int pdg = std::abs(particle->PdgCode());
248  if (pdg == 11 // electron
249  || pdg == 13 //muon
250  || pdg == 15 //tau
251  || pdg == 211 //charged pion
252  || pdg == 321 //charged kaon
253  || pdg == 2212 //proton
254  || pdg == 2214 //delta
255  || pdg == 2224 //delta
256  || pdg == 3222 //sigma
257  || pdg == 3112 //sigma
258  || pdg == 3312 //xi
259  || pdg == 3334 //omega
260  ) {
261  particle_vector.emplace_back(*particle);
262  }
263  }
264 }
265 
267  bool& pass_check,
268  geo::Geometry const& geometry)
269 {
270 
271  pass_check = false;
272 
273  const size_t numtraj = particle.NumberTrajectoryPoints();
274  size_t t_iter = 0;
275  while (t_iter < numtraj) {
276  try {
277  // check if the particle is inside a TPC
278  geo::Point_t const pos{particle.Vx(t_iter), particle.Vy(t_iter), particle.Vz(t_iter)};
279  geometry.PositionToTPC(pos);
280  }
281  catch (cet::exception& e) {
282  ++t_iter;
283  continue;
284  }
285  break;
286  }
287 
288  if (t_iter == numtraj) return 0;
289 
290  pass_check = true;
291  return particle.T(t_iter);
292 }
293 
295  std::vector<recob::OpFlash> const& flash_vector,
296  std::vector<simb::MCParticle> const& particle_vector,
297  float const& ns_per_PMT_tick,
298  geo::Geometry const& geometry)
299 {
300  fMatchIndex = 0;
301  fMatchIndex_NotNu = 0;
302  int lastFlashID = -1;
303 
304  for (size_t i_particle = 0; i_particle < particle_vector.size(); i_particle++) {
305 
306  simb::MCParticle const& my_particle(particle_vector.at(i_particle));
307  bool pass_check = false;
308  const float particle_time = update_MC_particle_time(my_particle, pass_check, geometry);
309  if (!pass_check) continue;
310 
311  for (size_t i_flash = 0; i_flash < flash_vector.size(); i_flash++) {
312 
313  recob::OpFlash const& my_flash(flash_vector.at(i_flash));
314  if (my_flash.TotalPE() < fPEMin) continue;
315 
316  const float flash_time = my_flash.Time() * ns_per_PMT_tick;
317 
318  fTimeDiff->Fill(particle_time - flash_time);
319  fTimeDiff_fine->Fill(particle_time - flash_time);
320 
321  fParticleID = i_particle;
322  fParticleTime = particle_time;
323  fParticleVx = my_particle.Vx(0);
324  fParticleVy = my_particle.Vy(0);
325  fParticleVz = my_particle.Vz(0);
326  fParticleMother = my_particle.Mother();
327  fParticleTrackID = my_particle.TrackId();
328  fFlashID = i_flash;
329  fFlashTime = flash_time;
330  fFlashTimeWidth = my_flash.TimeWidth() * ns_per_PMT_tick;
331  fFlashY = my_flash.YCenter();
332  fFlashZ = my_flash.ZCenter();
333  fFlashYWidth = my_flash.YWidth();
334  fFlashZWidth = my_flash.ZWidth();
335  fFlashPE = my_flash.TotalPE();
336  fFlashOnBeamTime = my_flash.OnBeamTime();
337 
338  bool beam_match = ((std::abs(particle_time - flash_time) / fFlashTimeWidth) < fTimeMatchMax &&
340  bool nonbeam_match =
341  ((std::abs(particle_time - flash_time) / fFlashTimeWidth) < fTimeMatchMax &&
343 
344  if (beam_match) {
345  fMatchTree_PF->Fill();
346  fMatchIndex++;
347 
348  fFlash_match_vector.at(i_flash).particle_indices.push_back(i_particle);
349  fParticle_match_vector.at(i_particle).flash_indices.push_back(i_flash);
350  }
351  else if (nonbeam_match) {
352  if (lastFlashID != fFlashID) {
353  fMatchTree_PF_NotNu->Fill();
355  lastFlashID = fFlashID;
356  }
357  }
358 
359  } //end inner loop over particles
360 
361  } //end loop over flashes
362 
363 } //end match_flashes_to_particles
double E(const int i=0) const
Definition: MCParticle.h:234
unsigned int NumberTrajectoryPoints() const
Definition: MCParticle.h:219
int PdgCode() const
Definition: MCParticle.h:213
void match_flashes_to_particles(std::vector< recob::OpFlash > const &, std::vector< simb::MCParticle > const &, float const &, geo::Geometry const &)
OpticalRecoAna(const fhicl::ParameterSet &)
Int_t ipart
Definition: Style.C:10
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
list_type::const_iterator const_iterator
Definition: ParticleList.h:132
double Mass() const
Definition: MCParticle.h:240
enum simb::_ev_origin Origin_t
event origin types
constexpr auto abs(T v)
Returns the absolute value of the argument.
void analyze(const art::Event &)
std::vector< flash_match > fFlash_match_vector
std::vector< size_t > track_indices
bool isRealData() const
Definition: Event.cc:53
Particle class.
RunNumber_t run() const
Definition: EventID.h:98
int TrackId() const
Definition: MCParticle.h:211
simb::Origin_t get_MC_particle_origin(simb::MCParticle const &)
std::vector< size_t > flash_indices
double Time() const
Definition: OpFlash.h:118
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:65
void beginJob()
Definition: Breakpoints.cc:14
const art::Ptr< simb::MCTruth > & TrackIdToMCTruth_P(int id) const
TPCGeo const & PositionToTPC(Point_t const &point) const
Returns the TPC at specified location.
T get(std::string const &key) const
Definition: ParameterSet.h:314
double T(const int i=0) const
Definition: MCParticle.h:225
iterator begin()
Definition: ParticleList.h:305
std::vector< size_t > flash_indices
Provides recob::Track data product.
The geometry of one entire detector, as served by art.
Definition: Geometry.h:181
#define MF_LOG_INFO(category)
const sim::ParticleList & ParticleList() const
double Vx(const int i=0) const
Definition: MCParticle.h:222
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:180
bool getByLabel(std::string const &label, std::string const &instance, Handle< PROD > &result) const
std::vector< particle_match > fParticle_match_vector
void get_MC_particle_list(sim::ParticleList const &, std::vector< simb::MCParticle > &)
double Vz(const int i=0) const
Definition: MCParticle.h:224
std::vector< size_t > particle_indices
EventNumber_t event() const
Definition: EventID.h:116
float update_MC_particle_time(simb::MCParticle const &, bool &, geo::Geometry const &)
std::vector< size_t > particle_indices
TCEvent evt
Definition: DataStructs.cxx:8
Float_t e
Definition: plot.C:35
std::vector< size_t > track_indices
std::vector< track_match > fTrack_match_vector
EventID id() const
Definition: Event.cc:23
double Vy(const int i=0) const
Definition: MCParticle.h:223
art framework interface to geometry description
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
Beam neutrinos.
Definition: MCTruth.h:23