MichelEventSelection_module.cc
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////
2 // Class: MichelReco
3 // Module Type: analyzer
4 // File: MichelReco_test.cc
5 //
6 // Michel electron event selection based on finding a cluster of
7 // Michel-like hits near the end of reconstructed tracks
8 // clusters are required in all three planes in order to select
9 // an event as from a Michel electron
10 //
11 // Generated at Tue Mar 21 06:06:49 2017 by Aiden Reynolds using artmod
12 // from cetpkgsupport v1_11_00.
13 ////////////////////////////////////////////////////////////////////////
14 
34 
37 #include "canvas/Persistency/Common/FindManyP.h"
43 #include "art_root_io/TFileService.h"
45 #include "fhiclcpp/ParameterSet.h"
47 
49 
50 #include "TTree.h"
51 #include "TH2D.h"
52 #include "TCanvas.h"
53 
54 #include <fstream>
55 
56 // Maximum number of tracks
57 //constexpr int kMaxTrack = 1000; // unused
58 
59 namespace MichelReco {
60 
61 class MichelReco;
62 
63 class MichelReco : public art::EDAnalyzer {
64 public:
65  explicit MichelReco(fhicl::ParameterSet const & p);
66  // The destructor generated by the compiler is fine for classes
67  // without bare pointers or other resource use.
68 
69  // Plugins should not be copied or assigned.
70  MichelReco(MichelReco const &) = delete;
71  MichelReco(MichelReco &&) = delete;
72  MichelReco & operator = (MichelReco const &) = delete;
73  MichelReco & operator = (MichelReco &&) = delete;
74 
75  // Required functions.
76  void analyze(art::Event const & e) override;
77 
78  // Selected optional functions
79  void beginJob() override;
80  void endJob() override;
81  void beginRun(const art::Run& run) override;
82  void reconfigure(fhicl::ParameterSet const& p) ;
83 
84  // My functions
85 
86  // check if a position is inside the fiducial volume
87  bool insideFidVol(double pos[3]);
88 
89  // check if a hit is close to the projected 2d end of a track
90  bool hitCloseToTrackEnd(detinfo::DetectorPropertiesData const& detProp,
91  double radius, double end[3],
92  double end2D[2], recob::Hit hit,
93  geo::GeometryCore const & geom);
94 
95  // match a reco track to the true particles track id
96  int trackMatching (int trackIndex,
97  art::FindManyP<recob::Hit> hitsFromTracks);
98 
99  // check if a true particle is a decaying muon
100  bool isMuonDecaying (simb::MCParticle particle,
101  std::vector<simb::MCParticle> particles);
102 
103  // takes vector of hits and checks that the majority
104  // of the charge in these hits is from a michel
105  bool areHitsMichel(detinfo::DetectorClocksData const& clockData,
106  const std::vector<recob::Hit> & hits );
107 
109 
110 private:
111  size_t fEvNumber;
112 
113  TCanvas * c;
114 
115  // Reconstruction parameters
116  double fRadiusThreshold; // Radius for hits in event selection
117  int fNumberThreshold; // Selection threshold for number of close hits
118  double fCNNThreshold; // CNN output threshold for selection
119 
120  int fNumberCloseHitsStart[3]; // Number of hits within selection radius
121  int fNumberCloseHitsEnd[3]; // Number of hits within selection radius
122 
123  // Purity and Efficiency Numbers
124  double fYesSelected; // Number of correctly selected events for each set of reco params
125  double fNoSelected; // Number of wrongly selected events " "
126  int fNMichel;
127 
128  // fhicl parameters
129  int fBestview; // Best plane, default collection
130  art::InputTag fTrackModuleLabel; // Module label from track recnstrucion
131  art::InputTag fNNetModuleLabel; // Module label for CNN
132  art::InputTag fParticleModuleLabel; // Module label for particle simulation
133  double fFidVolCut; // Size of cut to select a fiducial volume
134 };
135 
136 
138  :
139  EDAnalyzer(p),
140  fCalorimetryAlg(p.get<fhicl::ParameterSet>("CalorimetryAlg"))
141 {
142  reconfigure(p);
143 }
144 
146 {
148 }
149 
150 void MichelReco::endJob()
151 {
152  mf::LogVerbatim("MichelReco") << "MichelReco finished job";
153 
154  std::ofstream michelRecoOut;
155  michelRecoOut.open("test.txt");
156  michelRecoOut << "nMichel Purity Efficiency" << std::endl;
157 
158  double purity = fYesSelected / ( fYesSelected + fNoSelected );
159  double efficiency = fYesSelected/ fNMichel;
160 
161  michelRecoOut << fNMichel << " " << purity << " " << efficiency << std::endl;
162  michelRecoOut.close();
163 }
164 
165 void MichelReco::beginRun(const art::Run&)
166 {
168 }
169 
171 {
172 
173  fEvNumber = evt.id().event();
174  std::cout << "Michel event selection is on event " << fEvNumber << std::endl;
175 
176  // find all decaying muons in truth
177  auto const & particles = *evt.getValidHandle<std::vector<simb::MCParticle>>( fParticleModuleLabel );
178  for ( auto const & particle : particles ) {
179  if ( abs(particle.PdgCode()) == 13 ) {
180  double mcEnd[3] = { particle.EndX(), particle.EndY(), particle.EndZ() };
181  if ( isMuonDecaying( particle, particles ) && insideFidVol( mcEnd ) ) {
182  fNMichel += 1;
183  }
184  }
185  }
186 
187  // Get the reconstructed objects, tracks and hits
188  auto const & trackHandle = evt.getValidHandle<std::vector<recob::Track>>( fTrackModuleLabel );
189  auto const & tracks = * trackHandle;
190  art::FindManyP<recob::Hit> hitsFromTracks( trackHandle, evt, fTrackModuleLabel );
191 
192  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService>()->DataFor(evt);
193  auto const detProp = art::ServiceHandle<detinfo::DetectorPropertiesService>()->DataFor(evt, clockData);
194 
195  // loop over tracks
196  for (auto const & track : tracks) {
197 
198  // find best true trask ID for this track
199  //int bestTrackId = trackMatching( &track - &tracks[0], hitsFromTracks );
200 
201  // find track start and end
202  auto const & trackStart = track.Vertex<TVector3>();
203  double start[3] = { trackStart.X(), trackStart.Y(), trackStart.Z() };
204  auto const & trackEnd = track.End<TVector3>();
205  double end[3] = { trackEnd.X(), trackEnd.Y(), trackEnd.Z() };
206 
207  // Check if the track starts or ends in the fiducial volume
208  bool startInFidVol = insideFidVol( start );
209  bool endInFidVol = insideFidVol( end );
210  if ( startInFidVol || endInFidVol ) {
211 
212  // reset hit counts
213  for (int plane = 0; plane < 3; plane++) {
214  fNumberCloseHitsStart[ plane ] = 0; fNumberCloseHitsEnd[ plane ] = 0;
215  }
216 
217  // get the hit results helper
218  anab::MVAReader<recob::Hit,4> hitResults( evt, fNNetModuleLabel );
219 
220  // loop over hits store the selected hits
221  std::vector< recob::Hit > taggedHitsStart;
222  std::vector< recob::Hit > taggedHitsEnd;
223  for ( size_t h = 0; h < hitResults.size(); ++h ) {
224 
225  // cnn output vector: [em,trk,none,michel]
226  std::array<float,4> cnn_out = hitResults.getOutput( h );
227 
228  // keep hits with large CNN values
229  if ( cnn_out[hitResults.getIndex("michel")] > fCNNThreshold ) {
230 
231  // need to check at both ends of the track
232  if ( startInFidVol ) {
233 
234  // In each plane check if the michel tagged hits are close to the end of the track
235  for ( int plane = 0; plane < 3; plane++ ) {
236 
237  // project the track onto the plane
239  auto const & trackStart2D = pma::GetProjectionToPlane( trackStart, plane, geom.FindTPCAtPosition( start ).TPC, geom.FindCryostatAtPosition( start ) );
240  double start2D[2] = {trackStart2D.X(), trackStart2D.Y()};
241 
242  // get the hit itself
243  const recob::Hit & hit = hitResults.item(h);
244  if (hit.View() == plane) {
245 
246  // check that the hit is close to the track endpoint
247  // and add to tagged hits if so
248  if ( hitCloseToTrackEnd( detProp, fRadiusThreshold, start, start2D, hit, geom ) ) {
249  fNumberCloseHitsStart[ plane ] += 1;
250  if ( plane == 2 ) { taggedHitsStart.push_back( hit ); };
251  }
252 
253  }
254 
255  }
256 
257  }
258  if ( endInFidVol ) {
259 
260  // In each plane check if the michel tagged hits are close to the end of the track
261  for ( int plane = 0; plane < 3; plane++ ) {
262 
263  // project the track onto the plane
265  auto const & trackEnd2D = pma::GetProjectionToPlane( trackEnd, plane, geom.FindTPCAtPosition( end ).TPC, geom.FindCryostatAtPosition( end ) );
266  double end2D[2] = {trackEnd2D.X(), trackEnd2D.Y()};
267 
268  // get the hit itself
269  const recob::Hit & hit = hitResults.item(h);
270  if (hit.View() == plane) {
271 
272  // check that the hit is close to the track endpoint
273  // and add to tagged hits if so
274  if ( hitCloseToTrackEnd( detProp, fRadiusThreshold, end, end2D, hit, geom ) ) {
275  fNumberCloseHitsEnd[ plane ] += 1;
276  if ( plane == 2 ) { taggedHitsEnd.push_back( hit ); }
277  }
278 
279  }
280 
281  }
282 
283  }
284 
285  }
286 
287  } // end of loop over hits
288 
289  // event selection decision: clusters of hits in all planes at one end of the track
290  bool startSelected = ( fNumberCloseHitsStart[0] > fNumberThreshold && fNumberCloseHitsStart[1] > fNumberThreshold && fNumberCloseHitsStart[2] > fNumberThreshold );
291  bool endSelected = ( fNumberCloseHitsEnd[0] > fNumberThreshold && fNumberCloseHitsEnd[1] > fNumberThreshold && fNumberCloseHitsEnd[2] > fNumberThreshold );
292  bool eventSelected = ( startSelected || endSelected );
293  if ( startSelected && endSelected ) { eventSelected = false; }
294 
295  // check if the event was correclty tagged
296  // i.e. do the tagged hits correspond to a michel
297  bool particleIsMichel(false);
298  if (eventSelected) {
299  if ( startSelected ) { particleIsMichel = areHitsMichel(clockData, taggedHitsStart); }
300  if ( endSelected ) { particleIsMichel = areHitsMichel(clockData, taggedHitsEnd); }
301  }
302 
303  // update purity and efficiecny numbers and draw example events
304  if ( particleIsMichel && eventSelected ) {
305 
306  fYesSelected += 1;
307 
308  // plot the region around track end to see what the event is
309  // if ( startSelected ) {
310  //
311  // for (int plane = 0; plane < 3; plane++) {
312  //
313  // geo::GeometryCore const & geom = *art::ServiceHandle<geo::Geometry>();
314  // auto const & trackStart2D = pma::GetProjectionToPlane(trackStart, plane, geom.FindTPCAtPosition(start).TPC, geom.FindCryostatAtPosition(start));
315  // double start2D[2] = {trackStart2D.X(), trackStart2D.Y()};
316 
317  // TH2D * histCNN = new TH2D("cnn", "Correctly Tagged", 200, start2D[0] - 20.0, start2D[0] +20.0, 200, start2D[1] - 20.0, start2D[1] + 20.0);
318  // TH2D * histCharge = new TH2D("charge", "Correctly Tagged", 200, start2D[0] - 20.0, start2D[0] + 20.0, 200, start2D[1] - 20.0, start2D[1] + 20.0);
319  // histCNN -> SetStats(0);
320  // histCharge -> SetStats(0);
321 
322  // for ( size_t h = 0; h< hitResults.size(); ++h ) {
323  // const recob::Hit & hit = hitResults.item(h);
324  // auto const & hitLocation = pma::WireDriftToCm(hit.WireID().Wire, hit.PeakTime(), plane, geom.FindTPCAtPosition(start).TPC, geom.FindCryostatAtPosition(start));
325  //
326  // if (hit.View() == plane) {
327  // histCNN -> Fill(hitLocation.X(), hitLocation.Y(), hitResults.getOutput(h)[hitResults.getIndex("michel")]);
328  // histCharge -> Fill(hitLocation.X(), hitLocation.Y(), hit.Integral());
329  // }
330  // }
331  //
332  // histCNN -> Draw("colz");
333  // c->SaveAs(Form("imgs/correctCNN%d_plane%d.png",bestTrackId, plane));
334  // histCharge-> Draw("colz");
335  // c->SaveAs(Form("imgs/correctCharge%d_plane%d.png",bestTrackId, plane));
336  //
337  // }
338  // }
339  // if ( endSelected ) {
340  //
341  // for (int plane = 0; plane < 3; plane++) {
342  //
343  // geo::GeometryCore const & geom = *art::ServiceHandle<geo::Geometry>();
344  // auto const & trackEnd2D = pma::GetProjectionToPlane(trackEnd, plane, geom.FindTPCAtPosition(end).TPC, geom.FindCryostatAtPosition(end));
345  // double end2D[2] = {trackEnd2D.X(), trackEnd2D.Y()};
346 
347  // TH2D * histCNN = new TH2D("cnn", "Correctly Tagged", 200, end2D[0] - 20.0, end2D[0] +20.0, 200, end2D[1] - 20.0, end2D[1] + 20.0);
348  // TH2D * histCharge = new TH2D("charge", "Correctly Tagged", 200, end2D[0] - 20.0, end2D[0] + 20.0, 200, end2D[1] - 20.0, end2D[1] + 20.0);
349  // histCNN -> SetStats(0);
350  // histCharge -> SetStats(0);
351 
352  // for ( size_t h = 0; h< hitResults.size(); ++h ) {
353  // const recob::Hit & hit = hitResults.item(h);
354  // auto const & hitLocation = pma::WireDriftToCm(hit.WireID().Wire, hit.PeakTime(), plane, geom.FindTPCAtPosition(end).TPC, geom.FindCryostatAtPosition(end));
355  //
356  // if (hit.View() == plane) {
357  // histCNN -> Fill(hitLocation.X(), hitLocation.Y(), hitResults.getOutput(h)[hitResults.getIndex("michel")]);
358  // histCharge -> Fill(hitLocation.X(), hitLocation.Y(), hit.Integral());
359  // }
360  // }
361  //
362  // histCNN -> Draw("colz");
363  // c->SaveAs(Form("imgs/correctCNN%d_plane%d.png",bestTrackId, plane));
364  // histCharge-> Draw("colz");
365  // c->SaveAs(Form("imgs/correctCharge%d_plane%d.png",bestTrackId, plane));
366  //
367  // }
368 
369  // }
370 
371  }
372  if ( !particleIsMichel && eventSelected ) {
373 
374  fNoSelected += 1;
375 
376  // plot the region around track end to see what the event is
377  // if ( startSelected ) {
378  //
379  // for (int plane = 0; plane < 3; plane++) {
380  //
381  // geo::GeometryCore const & geom = *art::ServiceHandle<geo::Geometry>();
382  // auto const & trackStart2D = pma::GetProjectionToPlane(trackStart, plane, geom.FindTPCAtPosition(start).TPC, geom.FindCryostatAtPosition(start));
383  // double start2D[2] = {trackStart2D.X(), trackStart2D.Y()};
384 
385  // TH2D * histCNN = new TH2D("cnn", "Incorrectly Tagged", 200, start2D[0] - 20.0, start2D[0] +20.0, 200, start2D[1] - 20.0, start2D[1] + 20.0);
386  // TH2D * histCharge = new TH2D("charge", "Incorrectly Tagged", 200, start2D[0] - 20.0, start2D[0] + 20.0, 200, start2D[1] - 20.0, start2D[1] + 20.0);
387  // histCNN -> SetStats(0);
388  // histCharge -> SetStats(0);
389 
390  // for ( size_t h = 0; h< hitResults.size(); ++h ) {
391  // const recob::Hit & hit = hitResults.item(h);
392  // auto const & hitLocation = pma::WireDriftToCm(hit.WireID().Wire, hit.PeakTime(), plane, geom.FindTPCAtPosition(start).TPC, geom.FindCryostatAtPosition(start));
393  //
394  // if (hit.View() == plane) {
395  // histCNN -> Fill(hitLocation.X(), hitLocation.Y(), hitResults.getOutput(h)[hitResults.getIndex("michel")]);
396  // histCharge -> Fill(hitLocation.X(), hitLocation.Y(), hit.Integral());
397  // }
398  // }
399  //
400  // histCNN -> Draw("colz");
401  // c->SaveAs(Form("imgs/incorrectCNN%d_plane%d.png",bestTrackId, plane));
402  // histCharge-> Draw("colz");
403  // c->SaveAs(Form("imgs/incorrectCharge%d_plane%d.png",bestTrackId, plane));
404  //
405  // }
406  // }
407  // if ( endSelected ) {
408  //
409  // for (int plane = 0; plane < 3; plane++) {
410  //
411  // geo::GeometryCore const & geom = *art::ServiceHandle<geo::Geometry>();
412  // auto const & trackEnd2D = pma::GetProjectionToPlane(trackEnd, plane, geom.FindTPCAtPosition(end).TPC, geom.FindCryostatAtPosition(end));
413  // double end2D[2] = {trackEnd2D.X(), trackEnd2D.Y()};
414 
415  // TH2D * histCNN = new TH2D("cnn", "Incorrectly Tagged", 200, end2D[0] - 20.0, end2D[0] +20.0, 200, end2D[1] - 20.0, end2D[1] + 20.0);
416  // TH2D * histCharge = new TH2D("charge", "Incorrectly Tagged", 200, end2D[0] - 20.0, end2D[0] + 20.0, 200, end2D[1] - 20.0, end2D[1] + 20.0);
417  // histCNN -> SetStats(0);
418  // histCharge -> SetStats(0);
419 
420  // for ( size_t h = 0; h< hitResults.size(); ++h ) {
421  // const recob::Hit & hit = hitResults.item(h);
422  // auto const & hitLocation = pma::WireDriftToCm(hit.WireID().Wire, hit.PeakTime(), plane, geom.FindTPCAtPosition(end).TPC, geom.FindCryostatAtPosition(end));
423  //
424  // if (hit.View() == plane) {
425  // histCNN -> Fill(hitLocation.X(), hitLocation.Y(), hitResults.getOutput(h)[hitResults.getIndex("michel")]);
426  // histCharge -> Fill(hitLocation.X(), hitLocation.Y(), hit.Integral());
427  // }
428  // }
429  //
430  // histCNN -> Draw("colz");
431  // c->SaveAs(Form("imgs/incorrectCNN%d_plane%d.png",bestTrackId, plane));
432  // histCharge-> Draw("colz");
433  // c->SaveAs(Form("imgs/incorrectCharge%d_plane%d.png",bestTrackId, plane));
434  //
435  // }
436  //
437  // }
438 
439  }
440 
441  }
442 
443  } // end of loop over tracks
444 
445 }
446 // // Checks if the hits from a given track match the track with a given index
447 // int MichelReco::trackMatching( int trackIndex, art::FindManyP<recob::Hit> hitsFromTracks )
448 // {
449 // std::map<int,double> trackID_E;
450 // art::ServiceHandle<cheat::BackTrackerService> bt_serv;
451 
452 // for (size_t h = 0; h < hitsFromTracks.at(trackIndex).size(); ++h)
453 // {
454 // for (auto const & id : bt_serv->HitToTrackIDEs(hitsFromTracks.at(trackIndex)[h]))
455 // {
456 // trackID_E[id.trackID] += id.energy;
457 // }
458 // }
459 
460 // double max_e = 0.0; double tot_e = 0.0;
461 // int best_id = 0;
462 // for (std::map<int,double>::iterator it = trackID_E.begin(); it != trackID_E.end(); ++it)
463 // {
464 // tot_e += it->second;
465 // if (it->second > max_e)
466 // {
467 // max_e = it->second;
468 // best_id = it->first;
469 // }
470 // }
471 
472 // if ((max_e > 0.0) && (true/*max_e > 0.5*trackID_sumen[best_id]*/) && (tot_e > 0.0))
473 // {
474 // return best_id;
475 // }
476 // else
477 // {
478 // return -999;
479 // }
480 
481 // }
482 
483 // checks if the particle responsible for a track has an associated muon decay
484 bool MichelReco::isMuonDecaying ( simb::MCParticle particle, std::vector<simb::MCParticle> particles ) {
485 
486  bool hasElectron = false, hasNuMu = false, hasNuE = false;
487 
488  unsigned int nSec = particle.NumberDaughters();
489  for (size_t d = 0; d < nSec; ++d)
490  {
491  for (auto const & daughter : particles)
492  {
493  if (daughter.Mother() == particle.TrackId())
494  {
495  int d_pdg = abs(daughter.PdgCode());
496  if (d_pdg == 11) hasElectron = true;
497  else if (d_pdg == 14) hasNuMu = true;
498  else if (d_pdg == 12) hasNuE = true;
499  }
500  }
501  }
502  return (hasElectron && hasNuMu && hasNuE);
503 
504 }
505 
506 // checks if a position is inside the fiducial volume
507 bool MichelReco::insideFidVol( double pos[3] ) {
508 
510  bool inside = false;
511 
512  geo::TPCID idtpc = geom.FindTPCAtPosition(pos);
513 
514  if (geom.HasTPC(idtpc)) {
515 
516  const geo::TPCGeo& tpcgeo = geom.GetElement(idtpc);
517  double minx = tpcgeo.MinX(); double maxx = tpcgeo.MaxX();
518  double miny = tpcgeo.MinY(); double maxy = tpcgeo.MaxY();
519  double minz = tpcgeo.MinZ(); double maxz = tpcgeo.MaxZ();
520 
521  for (size_t cryo = 0; cryo < geom.Ncryostats(); cryo++) {
522  const geo::CryostatGeo& cryostat = geom.Cryostat(cryo);
523  for (size_t tpc = 0; tpc < cryostat.NTPC(); tpc++) {
524  const geo::TPCGeo& tpcg = cryostat.TPC(tpc);
525  if (tpcg.MinX() < minx) minx = tpcg.MinX();
526  if (tpcg.MaxX() > maxx) maxx = tpcg.MaxX();
527  if (tpcg.MinY() < miny) miny = tpcg.MinY();
528  if (tpcg.MaxY() > maxy) maxy = tpcg.MaxY();
529  if (tpcg.MinZ() < minz) minz = tpcg.MinZ();
530  if (tpcg.MaxZ() > maxz) maxz = tpcg.MaxZ();
531  }
532  }
533 
534  double dista = fabs(minx - pos[0]);
535  double distb = fabs(pos[0] - maxx);
536  if ((pos[0] > minx) && (pos[0] < maxx) &&
537  (dista > fFidVolCut) && (distb > fFidVolCut)) inside = true;
538 
539  dista = fabs(miny - pos[1]);
540  distb = fabs(pos[1]-maxy);
541  if (inside && (pos[1] > miny) && (pos[1] < maxy) &&
542  (dista > fFidVolCut) && (distb > fFidVolCut)) inside = true;
543  else inside = false;
544 
545  dista = fabs(minz - pos[2]);
546  distb = fabs(pos[2] - maxz);
547  if (inside && (pos[2] > minz) && (pos[2] < maxz) &&
548  (dista > fFidVolCut) && (distb > fFidVolCut)) inside = true;
549  else inside = false;
550 
551  }
552  return inside;
553 }
554 
555 // checks if a 2d hit is close to a given position
556 bool MichelReco::hitCloseToTrackEnd(detinfo::DetectorPropertiesData const& detProp,
557  double radius, double end[3], double end2D[2], recob::Hit hit, geo::GeometryCore const & geom ) {
558 
559  bool close = false;
560 
561  auto const & hitLocation = pma::WireDriftToCm(detProp,
562  hit.WireID().Wire, hit.PeakTime(), hit.View(), geom.FindTPCAtPosition(end).TPC, geom.FindCryostatAtPosition(end));
563 
564  double deltaXToHit = hitLocation.X() - end2D[0];
565  double deltaYToHit = hitLocation.Y() - end2D[1];
566 
567  double displacementToHit = pow(pow(deltaXToHit,2)+pow(deltaYToHit,2),0.5);
568 
569  if (displacementToHit < radius) close = true;
570 
571  return close;
572 
573 }
574 
575 // checks if vector of hits come mostly from michel charge
576 bool MichelReco::areHitsMichel(detinfo::DetectorClocksData const& clockData,
577  const std::vector< recob::Hit > & hits ) {
578 
579  const simb::MCParticle * mcParticle = 0;
580 
583  std::unordered_map< int, double > trkIDE;
584  for ( auto const & hit : hits ) {
585  for ( auto const & ide : bt_serv->HitToTrackIDEs(clockData, hit) ) { trkIDE[ide.trackID] += ide.energy; }
586  }
587 
588  int best_id(0);
589  double tot_e(0), max_e(0);
590  for ( auto const & contrib : trkIDE ) {
591 
592  tot_e += contrib.second;
593  if ( contrib.second > max_e ) {
594  max_e = contrib.second;
595  best_id = contrib.first;
596  }
597  }
598 
599  if ( (max_e > 0) && (tot_e > 0) ) {
600  if ( best_id < 0 ) {
601  best_id = -best_id;
602  }
603  mcParticle = pi_serv->TrackIdToParticle_P( best_id );
604  }
605 
606  if (mcParticle != 0) {
607  return ( abs(mcParticle->PdgCode()) && ( mcParticle->Process() == "Decay" || mcParticle->Process() == "muMinusCaptureAtRest") ) ;
608  }
609  else {
610  std::cout << "No match found" << hits.size() << std::endl;
611  return false;
612  }
613 
614 }
615 
617 
618  c = new TCanvas( "canv", "canv" );
619 
620  fTrackModuleLabel = p.get<std::string>("TrackModuleLabel");
621  fNNetModuleLabel = p.get<std::string>("NNetModuleLabel");
622  fParticleModuleLabel = p.get<std::string>("ParticleModuleLabel");
623 
624  fBestview = p.get<int>("Bestview");
625 
626  fRadiusThreshold = p.get<double>("MichelCloseHitRadius");
627  fNumberThreshold = p.get<int>("CloseHitsThreshold");
628  fCNNThreshold = p.get<double>("CNNThreshSelect");
629  fFidVolCut = p.get<double>("FidVolCut");
630 
631  for ( int plane = 0; plane < 3; plane++ ) {
632  fNumberCloseHitsStart[ plane ] = 0; fNumberCloseHitsEnd[ plane ] = 0;
633  }
634 
635  fYesSelected = 0;
636  fNoSelected = 0;
637  fNMichel = 0;
638 
639  return;
640 }
641 
642 } // MichelReco namespace
643 
def analyze(root, level, gtrees, gbranches, doprint)
Definition: rootstat.py:69
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
Store parameters for running LArG4.
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
int PdgCode() const
Definition: MCParticle.h:212
CryostatGeo const & GetElement(geo::CryostatID const &cryoid) const
std::vector< sim::TrackIDE > HitToTrackIDEs(detinfo::DetectorClocksData const &clockData, recob::Hit const &hit) const
Container of LAr voxel information.
std::string string
Definition: nybbler.cc:12
const simb::MCParticle * TrackIdToParticle_P(int id) const
geo::WireID WireID() const
Definition: Hit.h:233
constexpr T pow(T x)
Definition: pow.h:72
double MinX() const
Returns the world x coordinate of the start of the box.
Definition: BoxBoundedGeo.h:88
Geometry information for a single TPC.
Definition: TPCGeo.h:38
int getIndex(const std::string &name) const
Index of column with given name, or -1 if name not found.
Definition: MVAReader.h:82
TVector2 WireDriftToCm(detinfo::DetectorPropertiesData const &detProp, unsigned int wire, float drift, unsigned int plane, unsigned int tpc, unsigned int cryo)
Definition: Utilities.cxx:294
double MaxX() const
Returns the world x coordinate of the end of the box.
Definition: BoxBoundedGeo.h:91
geo::View_t View() const
View for the plane of the hit.
Definition: Hit.h:232
WireID_t Wire
Index of the wire within its plane.
Definition: geo_types.h:580
Geometry information for a single cryostat.
Definition: CryostatGeo.h:43
unsigned int Ncryostats() const
Returns the number of cryostats in the detector.
std::string Process() const
Definition: MCParticle.h:215
Particle class.
T const & item(size_t key) const
Access data product at index "key".
Definition: MVAReader.h:43
int NumberDaughters() const
Definition: MCParticle.h:217
art framework interface to geometry description
Definition: Run.h:17
int TrackId() const
Definition: MCParticle.h:210
geo::TPCID FindTPCAtPosition(double const worldLoc[3]) const
Returns the ID of the TPC at specified location.
T abs(T value)
int close(int)
Closes the file descriptor fd.
const double e
Encapsulates the information we want store for a voxel.
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:67
void beginJob()
Definition: Breakpoints.cc:14
virtual void reconfigure(fhicl::ParameterSet const &pset)
T get(std::string const &key) const
Definition: ParameterSet.h:271
double MinZ() const
Returns the world z coordinate of the start of the box.
ValidHandle< PROD > getValidHandle(InputTag const &tag) const
Definition: DataViewImpl.h:441
p
Definition: test.py:223
unsigned int NTPC() const
Number of TPCs in this cryostat.
Definition: CryostatGeo.h:181
CryostatGeo const & Cryostat(geo::CryostatID const &cryoid) const
Returns the specified cryostat.
size_t size() const
Get the number of contained items (no. of data product objects equal to no. of feature vectors)...
Definition: MVAReader.h:67
The data type to uniquely identify a TPC.
Definition: geo_types.h:386
Description of geometry of one entire detector.
Detector simulation of raw signals on wires.
double MaxY() const
Returns the world y coordinate of the end of the box.
bool HasTPC(geo::TPCID const &tpcid) const
Returns whether we have the specified TPC.
Definition: tracks.py:1
Implementation of the Projection Matching Algorithm.
float PeakTime() const
Time of the signal peak, in tick units.
Definition: Hit.h:218
Declaration of signal hit object.
Contains all timing reference information for the detector.
const TPCGeo & TPC(unsigned int itpc) const
Return the itpc&#39;th TPC in the cryostat.
Definition: CryostatGeo.cxx:93
double MaxZ() const
Returns the world z coordinate of the end of the box.
TVector2 GetProjectionToPlane(const TVector3 &p, unsigned int plane, unsigned int tpc, unsigned int cryo)
Definition: Utilities.cxx:270
Provides recob::Track data product.
EventNumber_t event() const
Definition: EventID.h:116
2D representation of charge deposited in the TDC/wire plane
Definition: Hit.h:48
TCEvent evt
Definition: DataStructs.cxx:7
auto const & get(AssnsNode< L, R, D > const &r)
Definition: AssnsNode.h:115
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:406
Collection of Physical constants used in LArSoft.
double MinY() const
Returns the world y coordinate of the start of the box.
geo::CryostatID::CryostatID_t FindCryostatAtPosition(geo::Point_t const &worldLoc) const
Returns the index of the cryostat at specified location.
std::array< float, N > getOutput(size_t key) const
Get copy of the MVA output vector at index "key".
Definition: MVAReader.h:129
EventID id() const
Definition: Event.cc:34
QTextStream & endl(QTextStream &s)