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  };
40  std::vector<size_t> flash_indices;
41  std::vector<size_t> track_indices;
42  };
43 
45  public:
46 
48 
49  void beginJob();
50  void analyze (const art::Event&);
51 
52  private:
53 
54  //fcl parameters here
58  float fPEMin;
60 
61  std::vector<flash_match> fFlash_match_vector;
62  std::vector<track_match> fTrack_match_vector;
63  std::vector<particle_match> fParticle_match_vector;
64 
65  void get_MC_particle_list(sim::ParticleList const& ,std::vector<simb::MCParticle> & );
66  simb::Origin_t get_MC_particle_origin(simb::MCParticle const& );
67  float update_MC_particle_time(simb::MCParticle const&, bool& ,geo::Geometry const&);
68 
69  //matching functions
70  void match_flashes_to_tracks(std::vector<recob::OpFlash> const& ,
71  std::vector<recob::Track> const&);
72  void compare_track_and_flash(recob::Track const&,
73  recob::OpFlash const&,
74  bool &);
75 
76  void match_flashes_to_particles(std::vector<recob::OpFlash> const&,
77  std::vector<simb::MCParticle> const&,
78  float const&,
79  geo::Geometry const&);
80  void compare_particle_and_flash(simb::MCParticle const&,
81  recob::OpFlash const&,
82  bool &,
83  float const&,
84  geo::Geometry const&);
85 
86  void match_flashes_to_particles(std::vector<recob::Track> const&,
87  std::vector<simb::MCParticle> const&,
88  geo::Geometry const&);
89  void compare_particle_and_track(simb::MCParticle const&,
90  recob::Track const&,
91  bool &,
92  geo::Geometry const&);
93 
94  void FillMatchTree_PF(std::vector<recob::OpFlash> const&,
95  std::vector<simb::MCParticle> const&,
96  float const&,
97  geo::Geometry const&);
98 
99 
100  TH1F *fTimeDiff;
103 
106  int fRun;
107  int fEvent;
112  float fParticleVx;
113  float fParticleVy;
114  float fParticleVz;
115  int fFlashID;
116  float fFlashTime;
118  float fFlashY;
119  float fFlashZ;
122  float fFlashPE;
126 
127  };
128 
129 }
130 
131 namespace opreco {
133 }
134 
135 
136  // Constructor
138 {
139 
140  // Indicate that the Input Module comes from .fcl
141  fFlashModuleLabel = pset.get<std::string>("FlashModule");
142  fTrackModuleLabel = pset.get<std::string>("TrackModule");
143  fKineticEnergyMin = pset.get<float>("KineticEnergyMin");
144  fPEMin = pset.get<float>("PEMin");
145  fTimeMatchMax = pset.get<float>("TimeMatchMax");
146 
147  fFlash_match_vector.clear();
148  fTrack_match_vector.clear();
149  fParticle_match_vector.clear();
150 }
151 
152 
153 
154 // Do something here to setup the file (like make a TTree)
156 {
158  fTimeDiff = tfs->make<TH1F>("htdiff","Time difference between particles and flashes; t_diff (ns); flash/particle pairs",1e3,-5e6,5e6);
159  fTimeDiff_fine = tfs->make<TH1F>("htdiff_fine","Time difference between particles and flashes; t_diff (ns); flash/particle pairs",100,-1000,1000);
160  fNBeamFlashes = tfs->make<TH1I>("hNBeamFlashes","Number of flashes OnBeamTime per event; N_{Flashes}; Events",5,0,5);
161 
162  fMatchTree_PF = tfs->make<TTree>("MatchTree_PF","MatchTree_PF");
163  fMatchTree_PF->Branch("Run",&fRun,"Run/I");
164  fMatchTree_PF->Branch("Event",&fEvent,"Event/I");
165  fMatchTree_PF->Branch("p_id",&fParticleID,"p_id/I");
166  fMatchTree_PF->Branch("p_time",&fParticleTime,"p_time/F");
167  fMatchTree_PF->Branch("p_vx",&fParticleVx,"p_vx/F");
168  fMatchTree_PF->Branch("p_vy",&fParticleVy,"p_vy/F");
169  fMatchTree_PF->Branch("p_vz",&fParticleVz,"p_vz/F");
170  fMatchTree_PF->Branch("p_mid",&fParticleMother,"p_mid/I");
171  fMatchTree_PF->Branch("p_trackid",&fParticleTrackID,"p_trackid/I");
172  fMatchTree_PF->Branch("FlashID",&fFlashID,"flash_id/I");
173  fMatchTree_PF->Branch("f_time",&fFlashTime,"f_time/F");
174  fMatchTree_PF->Branch("f_timewidth",&fFlashTimeWidth,"f_timewidth/F");
175  fMatchTree_PF->Branch("f_y",&fFlashY,"f_y/F");
176  fMatchTree_PF->Branch("f_z",&fFlashZ,"f_z/F");
177  fMatchTree_PF->Branch("f_ywidth",&fFlashYWidth,"f_ywidth/F");
178  fMatchTree_PF->Branch("f_zwidth",&fFlashYWidth,"f_zwidth/F");
179  fMatchTree_PF->Branch("f_onbeamtime",&fFlashOnBeamTime,"f_onbeamtime/I");
180  fMatchTree_PF->Branch("f_pe",&fFlashPE,"f_pe/F");
181  fMatchTree_PF->Branch("matchIndex",&fMatchIndex,"matchIndex/I");
182 
183  fMatchTree_PF_NotNu = tfs->make<TTree>("MatchTree_PF_NotNu","MatchTree_PF_NotNu");
184  fMatchTree_PF_NotNu->Branch("Run",&fRun,"Run/I");
185  fMatchTree_PF_NotNu->Branch("Event",&fEvent,"Event/I");
186  fMatchTree_PF_NotNu->Branch("p_id",&fParticleID,"p_id/I");
187  fMatchTree_PF_NotNu->Branch("p_time",&fParticleTime,"p_time/F");
188  fMatchTree_PF_NotNu->Branch("p_vx",&fParticleVx,"p_vx/F");
189  fMatchTree_PF_NotNu->Branch("p_vy",&fParticleVy,"p_vy/F");
190  fMatchTree_PF_NotNu->Branch("p_vz",&fParticleVz,"p_vz/F");
191  fMatchTree_PF_NotNu->Branch("p_mid",&fParticleMother,"p_mid/I");
192  fMatchTree_PF_NotNu->Branch("p_trackid",&fParticleTrackID,"p_trackid/I");
193  fMatchTree_PF_NotNu->Branch("FlashID",&fFlashID,"flash_id/I");
194  fMatchTree_PF_NotNu->Branch("f_time",&fFlashTime,"f_time/F");
195  fMatchTree_PF_NotNu->Branch("f_timewidth",&fFlashTimeWidth,"f_timewidth/F");
196  fMatchTree_PF_NotNu->Branch("f_y",&fFlashY,"f_y/F");
197  fMatchTree_PF_NotNu->Branch("f_z",&fFlashZ,"f_z/F");
198  fMatchTree_PF_NotNu->Branch("f_ywidth",&fFlashYWidth,"f_ywidth/F");
199  fMatchTree_PF_NotNu->Branch("f_zwidth",&fFlashYWidth,"f_zwidth/F");
200  fMatchTree_PF_NotNu->Branch("f_onbeamtime",&fFlashOnBeamTime,"f_onbeamtime/I");
201  fMatchTree_PF_NotNu->Branch("f_pe",&fFlashPE,"f_pe/F");
202  fMatchTree_PF_NotNu->Branch("matchIndex",&fMatchIndex_NotNu,"matchIndex/I");
203 
204 }
205 
206 
207 
208 // The analyzer itself
210 {
211 
212  //get flag for MC
213  const bool is_MC= !(evt.isRealData());
214 
215  fRun = evt.id().run();
216  fEvent = evt.id().event();
217 
218  //first get out track, flash, and particle list handles
220  evt.getByLabel(fFlashModuleLabel, flash_handle);
221  std::vector<recob::OpFlash> const& flash_vector(*flash_handle);
222  fFlash_match_vector.resize(flash_vector.size());
223 
224  MF_LOG_INFO ("OpticalRecoAna")
225  << "Number of flashes is " << flash_vector.size() << std::flush;
226 
227  //art::Handle< std::vector<recob::Track> > track_handle;
228  //evt.getByLabel(fTrackModuleLabel, track_handle);
229  //std::vector<recob::Track> const& track_vector(*track_handle);
230  //fTrack_match_vector.resize(track_vector.size());
231 
232  //MF_LOG_INFO ("OpticalRecoAna")
233  //<< "Number of tracks is " << track_vector.size() << std::flush;
234 
235  //match_flashes_to_tracks(flash_vector, track_vector);
236 
237  //all this for the MC matching
238  if(is_MC){
239 
241  std::vector<simb::MCParticle> particle_list;
242  get_MC_particle_list(pi_serv->ParticleList(),particle_list);
243  fParticle_match_vector.resize(particle_list.size());
244 
245  mf::LogInfo("OpticalRecoAna")
246  << "Number of MC particles is " << particle_list.size();
247 
248 
250  const float ns_per_PMT_tick = 1e3;// already converted to microseconds//( 1e3 / odp->SampleFreq()) ; //SampleFreq is in MHz
252 
253  match_flashes_to_particles(flash_vector,
254  particle_list,
255  ns_per_PMT_tick,
256  *geometry_handle);
257  /*
258  FillMatchTree_PF(flash_vector,
259  particle_list,
260  ns_per_PMT_tick,
261  *geometry_handle);
262  */
263  int n_flashes = 0;
264  for(auto const& my_flash : flash_vector){
265  if(my_flash.OnBeamTime()==1) n_flashes++;
266  }
267  fNBeamFlashes->Fill(n_flashes);
268 
269  //check_flash_matches();
270 
271  //match_tracks_to_particles(track_handle,particle_list);
272 
273  }
274 
275 }
276 
279  return (pi_serv->TrackIdToMCTruth_P(particle.TrackId()))->Origin();
280 }
281 
282 void opreco::OpticalRecoAna::get_MC_particle_list(sim::ParticleList const& plist,std::vector<simb::MCParticle> & particle_vector) {
283 
284  for(sim::ParticleList::const_iterator ipart = plist.begin(); ipart != plist.end(); ++ipart) {
285 
286  const simb::MCParticle* particle = (*ipart).second;
287  /*
288  std::cout << "Particle " << particle_vector.size() << " (" << (*ipart).first << ") is " << particle->PdgCode() << " (mother=" << particle->Mother()
289  << ") with K_energy " << particle->E()-0.001*particle->Mass() << std::endl;
290  std::cout << "\t(X,Y,Z,T)=(" << particle->Vx() << "," << particle->Vy() << "," << particle->Vz() << "," << particle->T() << ")" << std::endl;
291  */
292  //do not store if it's below our energy cut
293  if( particle->E() < 0.001*particle->Mass() + fKineticEnergyMin ) continue;
294 
295  //check to see if it's a charged particle we expect to leave ionization
296  const int pdg = std::abs(particle->PdgCode());
297  if( pdg==11 // electron
298  || pdg==13 //muon
299  || pdg==15 //tau
300  || pdg==211 //charged pion
301  || pdg==321 //charged kaon
302  || pdg==2212 //proton
303  || pdg==2214 //delta
304  || pdg==2224 //delta
305  || pdg==3222 //sigma
306  || pdg==3112 //sigma
307  || pdg==3312 //xi
308  || pdg==3334 //omega
309  ) {
310  particle_vector.emplace_back(*particle);
311  //std::cout << "Particle " << particle_vector.size() << " (" << (*ipart).first << ") is " << pdg << " (status=" << particle->StatusCode()
312  // << ") with K_energy " << particle->E()-0.001*particle->Mass() << std::endl;
313  //std::cout << "\t(X,Y,Z,T)=(" << particle->Vx() << "," << particle->Vy() << "," << particle->Vz() << "," << particle->T() << ")" << std::endl;
314  }
315  }
316 
317 }
318 
319 float opreco::OpticalRecoAna::update_MC_particle_time(simb::MCParticle const& particle, bool & pass_check, geo::Geometry const& geometry){
320 
321  pass_check = false;
322 
323  unsigned int tpc = 0;
324  unsigned int cstat = 0;
325 
326  const size_t numtraj = particle.NumberTrajectoryPoints();
327  size_t t_iter = 0;
328  while(t_iter < numtraj){
329  try{
330  // check if the particle is inside a TPC
331  double pos[3] = {particle.Vx(t_iter), particle.Vy(t_iter), particle.Vz(t_iter)};
332  geometry.PositionToTPC(pos, tpc, cstat);
333  }
334  catch(cet::exception &e){
335  t_iter++;
336  continue;
337  }
338  break;
339  }
340 
341  if(t_iter == numtraj)
342  return 0;
343 
344  pass_check = true;
345  return particle.T(t_iter);
346 }
347 
348 void opreco::OpticalRecoAna::match_flashes_to_tracks(std::vector<recob::OpFlash> const& flash_vector,
349  std::vector<recob::Track> const& track_vector){
350  bool matching=false;
351 
352  for(size_t i_flash=0; i_flash < flash_vector.size(); i_flash++){
353 
354  recob::OpFlash const& my_flash( flash_vector.at(i_flash) );
355  if(my_flash.TotalPE() < fPEMin) continue;
356 
357  for(size_t i_track=0; i_track < track_vector.size(); i_track++){
358 
359  recob::Track const& my_track( track_vector.at(i_track) );
360 
361  matching=false;
362  compare_track_and_flash(my_track,my_flash,matching);
363  if(matching){
364  fFlash_match_vector.at(i_flash).track_indices.push_back(i_track);
365  fTrack_match_vector.at(i_track).flash_indices.push_back(i_flash);
366  }
367 
368  }//end inner loop over tracks
369 
370  }//end loop over flashes
371 
372 }//end match_flashes_to_tracks
373 
375  recob::OpFlash const& flash,
376  bool & matching){
377 }
378 
379 void opreco::OpticalRecoAna::match_flashes_to_particles(std::vector<recob::OpFlash> const& flash_vector,
380  std::vector<simb::MCParticle> const& particle_vector,
381  float const& ns_per_PMT_tick,
382  geo::Geometry const& geometry){
383 
384  fMatchIndex=0;
386  int lastFlashID = -1;
387 
388  for(size_t i_particle=0; i_particle < particle_vector.size(); i_particle++){
389 
390  simb::MCParticle const& my_particle( particle_vector.at(i_particle) );
391  bool pass_check = false;
392  const float particle_time = update_MC_particle_time(my_particle,pass_check,geometry);
393  if(!pass_check) continue;
394 
395  //std::cout << "Particle " << i_particle << " (" << my_particle.PdgCode() << ")" << particle_time << std::endl;
396 
397  for(size_t i_flash=0; i_flash < flash_vector.size(); i_flash++){
398 
399  recob::OpFlash const& my_flash( flash_vector.at(i_flash) );
400  if(my_flash.TotalPE() < fPEMin) continue;
401 
402  const float flash_time = my_flash.Time()*ns_per_PMT_tick;
403 
404  //if(my_flash.OnBeamTime())
405  //std::cout << "\tFlash " << i_flash << " time is " << flash_time << std::endl;
406 
407  fTimeDiff->Fill(particle_time-flash_time);
408  fTimeDiff_fine->Fill(particle_time-flash_time);
409 
410  fParticleID = i_particle;
411  fParticleTime = particle_time;
412  fParticleVx = my_particle.Vx(0);
413  fParticleVy = my_particle.Vy(0);
414  fParticleVz = my_particle.Vz(0);
415  fParticleMother = my_particle.Mother();
416  fParticleTrackID = my_particle.TrackId();
417  fFlashID = i_flash;
418  fFlashTime = flash_time;
419  fFlashTimeWidth = my_flash.TimeWidth()*ns_per_PMT_tick;
420  fFlashY = my_flash.YCenter();
421  fFlashZ = my_flash.ZCenter();
422  fFlashYWidth = my_flash.YWidth();
423  fFlashZWidth = my_flash.ZWidth();
424  fFlashPE = my_flash.TotalPE();
425  fFlashOnBeamTime = my_flash.OnBeamTime();
426 
427  bool beam_match = ((std::abs(particle_time - flash_time )/fFlashTimeWidth)<fTimeMatchMax &&
429  bool nonbeam_match = ((std::abs(particle_time - flash_time )/fFlashTimeWidth)<fTimeMatchMax &&
431 
432  if( beam_match ){
433  fMatchTree_PF->Fill();
434  fMatchIndex++;
435 
436  //std::cout << "\t\tParticle (x,y,z)=(" << my_particle.Vx() << "," << my_particle.Vy() << "," << my_particle.Vz() << std::endl;
437  //std::cout << "\t\tParticle PDG = " << my_particle.PdgCode() << " mother=" << my_particle.Mother() << std::endl;
438  //std::cout << "\t\tFlash (y,z) = ("
439  // << my_flash.YCenter() << " +/- " << my_flash.YWidth() << ","
440  // << my_flash.ZCenter() << " +/- " << my_flash.ZWidth() << std::endl;
441 
442  fFlash_match_vector.at(i_flash).particle_indices.push_back(i_particle);
443  fParticle_match_vector.at(i_particle).flash_indices.push_back(i_flash);
444  }
445  else if( nonbeam_match ){
446  if(lastFlashID!=fFlashID){
447  fMatchTree_PF_NotNu->Fill();
449  lastFlashID = fFlashID;
450  }
451  }
452 
453 
454  }//end inner loop over particles
455 
456  }//end loop over flashes
457 
458 }//end match_flashes_to_particles
459 
460 void opreco::OpticalRecoAna::FillMatchTree_PF(std::vector<recob::OpFlash> const& flash_vector,
461  std::vector<simb::MCParticle> const& particle_vector,
462  float const& ns_per_PMT_tick,
463  geo::Geometry const& geometry){
464 
465  for(size_t i_flash=0; i_flash < flash_vector.size(); i_flash++){
466 
467  recob::OpFlash const& my_flash( flash_vector.at(i_flash) );
468  const float flash_time = my_flash.Time()*ns_per_PMT_tick;
469 
470  for(auto i_particle : fFlash_match_vector.at(i_flash).particle_indices){
471 
472  simb::MCParticle const& my_particle( particle_vector.at(i_particle) );
473  bool pass_check = false;
474  const float particle_time = update_MC_particle_time(my_particle,pass_check,geometry);
475 
476  if(my_particle.Mother()==0 && my_particle.TrackId()>1e4){
477 
478  fParticleID = i_particle;
479  fParticleTime = particle_time;
480  fParticleVx = my_particle.Vx(0);
481  fParticleVy = my_particle.Vy(0);
482  fParticleVz = my_particle.Vz(0);
483  fFlashID = i_flash;
484  fFlashTime = flash_time;
485  fFlashY = my_flash.YCenter();
486  fFlashZ = my_flash.ZCenter();
487  fFlashYWidth = my_flash.YWidth();
488  fFlashZWidth = my_flash.ZWidth();
489 
490  fMatchTree_PF->Fill();
491 
492  return;
493  }
494 
495  }
496 
497  }
498 
499 }
500 
501 //currently unused...
503  recob::OpFlash const& flash,
504  bool & matching,
505  float const& ns_per_PMT_tick,
506  geo::Geometry const& geometry){
507 }
508 
509 void opreco::OpticalRecoAna::match_flashes_to_particles(std::vector<recob::Track> const& track_vector,
510  std::vector<simb::MCParticle> const& particle_vector,
511  geo::Geometry const& geometry){
512  bool matching=false;
513 
514  for(size_t i_track=0; i_track < track_vector.size(); i_track++){
515 
516  recob::Track const& my_track( track_vector.at(i_track) );
517 
518  for(size_t i_particle=0; i_particle < particle_vector.size(); i_particle++){
519 
520  simb::MCParticle const& my_particle( particle_vector.at(i_particle) );
521 
522  matching=false;
523  compare_particle_and_track(my_particle,my_track,matching,geometry);
524  if(matching){
525  fTrack_match_vector.at(i_track).particle_indices.push_back(i_track);
526  fParticle_match_vector.at(i_particle).track_indices.push_back(i_track);
527  }
528 
529  }//end inner loop over particles
530 
531  }//end loop over tracks
532 
533 }//end match_tracks_to_particles
534 
536  recob::Track const& track,
537  bool & matching,
538  geo::Geometry const& geometry){
539 }
def analyze(root, level, gtrees, gbranches, doprint)
Definition: rootstat.py:69
double E(const int i=0) const
Definition: MCParticle.h:233
unsigned int NumberTrajectoryPoints() const
Definition: MCParticle.h:218
int PdgCode() const
Definition: MCParticle.h:212
void match_flashes_to_particles(std::vector< recob::OpFlash > const &, std::vector< simb::MCParticle > const &, float const &, geo::Geometry const &)
OpticalRecoAna(const fhicl::ParameterSet &)
void compare_track_and_flash(recob::Track const &, recob::OpFlash const &, bool &)
std::string string
Definition: nybbler.cc:12
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
double Mass() const
Definition: MCParticle.h:239
enum simb::_ev_origin Origin_t
event origin types
void analyze(const art::Event &)
std::vector< flash_match > fFlash_match_vector
intermediate_table::const_iterator const_iterator
std::vector< size_t > track_indices
Particle class.
RunNumber_t run() const
Definition: EventID.h:98
art framework interface to geometry description
int TrackId() const
Definition: MCParticle.h:210
geo::TPCGeo const & PositionToTPC(geo::Point_t const &point) const
Returns the TPC at specified location.
simb::Origin_t get_MC_particle_origin(simb::MCParticle const &)
bool isRealData() const
T abs(T value)
std::vector< size_t > flash_indices
void FillMatchTree_PF(std::vector< recob::OpFlash > const &, std::vector< simb::MCParticle > const &, float const &, geo::Geometry const &)
double Time() const
Definition: OpFlash.h:106
bool getByLabel(std::string const &label, std::string const &instance, Handle< PROD > &result) const
Definition: DataViewImpl.h:633
const double e
void compare_particle_and_flash(simb::MCParticle const &, recob::OpFlash const &, bool &, float const &, geo::Geometry const &)
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:67
void beginJob()
Definition: Breakpoints.cc:14
const art::Ptr< simb::MCTruth > & TrackIdToMCTruth_P(int id) const
T get(std::string const &key) const
Definition: ParameterSet.h:271
QTextStream & flush(QTextStream &s)
double T(const int i=0) const
Definition: MCParticle.h:224
std::vector< size_t > flash_indices
The geometry of one entire detector, as served by art.
Definition: Geometry.h:196
void match_flashes_to_tracks(std::vector< recob::OpFlash > const &, std::vector< recob::Track > const &)
#define MF_LOG_INFO(category)
const sim::ParticleList & ParticleList() const
double Vx(const int i=0) const
Definition: MCParticle.h:221
std::vector< particle_match > fParticle_match_vector
void get_MC_particle_list(sim::ParticleList const &, std::vector< simb::MCParticle > &)
void compare_particle_and_track(simb::MCParticle const &, recob::Track const &, bool &, geo::Geometry const &)
Provides recob::Track data product.
double Vz(const int i=0) const
Definition: MCParticle.h:223
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:7
std::vector< size_t > track_indices
std::vector< track_match > fTrack_match_vector
EventID id() const
Definition: Event.cc:34
double Vy(const int i=0) const
Definition: MCParticle.h:222
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
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
Beam neutrinos.
Definition: MCTruth.h:23