RobustMCAna_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 // Class: RobustMCAna
3 // Plugin Type: analyzer (art v2_05_00)
4 // File: RobustMCAna_module.cc
5 //
6 // Generated at Sun Nov 20 14:28:42 2016 by Matthew Thiesse using cetskelgen
7 // from cetlib version v1_21_00.
8 ////////////////////////////////////////////////////////////////////////
9 
16 #include "art_root_io/TFileService.h"
18 #include "canvas/Persistency/Common/FindManyP.h"
19 #include "fhiclcpp/ParameterSet.h"
21 
39 
40 #include <algorithm>
41 #include "TMath.h"
42 #include "TTree.h"
43 #include "TH1.h"
44 #include "TH2.h"
45 
46 //for the counter position map
48 
49 namespace hit {
50  class RobustMCAna;
51 }
52 
54 public:
55  explicit RobustMCAna(fhicl::ParameterSet const & p);
56  // The compiler-generated destructor is fine for non-base
57  // classes without bare pointers or other resource use.
58 
59  // Plugins should not be copied or assigned.
60  RobustMCAna(RobustMCAna const &) = delete;
61  RobustMCAna(RobustMCAna &&) = delete;
62  RobustMCAna & operator = (RobustMCAna const &) = delete;
63  RobustMCAna & operator = (RobustMCAna &&) = delete;
64 
65  // Required functions.
66  void analyze(art::Event const & e) override;
67 
68 private:
69 
71  bool ValidTrigger(std::vector<unsigned int> evtTriggers, unsigned int & c1arg, unsigned int & c2arg, unsigned int & trignumarg);
72  void NumElectronsTofC(double & input);
73  void SumADCTofC(double & input);
74  void fCToSumADC(double & input);
75  double Purity(double tp, double fp);
76  double Efficiency(double tp, double fn);
77  double MCC(double tp, double fp, double fn, double tn);
78  double VMean(std::vector<double> v);
79 
80  // Struct to contain combined IDE information
81  struct MCHit {
83  int pdg;
84  std::vector<sim::IDE> idevec;
85  std::vector<unsigned short> tdcvec;
86  std::vector<double> chargevec;
87  std::vector<const simb::MCParticle *> particlevec;
88  };
89 
90  // FHICL parameters
93  bool fVerbose;
94  double mcscale;
95  int fNbins;
96  double preampGain;
98  double ADCtomV;
99 
100  // Histograms in the TFile
101  TH1D* hEventPurity; // aka Precision
102  TH1D* hEventEfficiency; // aka Recall
106  TH1D* hdQ;
107  TH2D* hChargeComp;
108  TH1D* hdT;
109  TH1D* hMCC;
110 
111  // Output TTrees
112  TTree * fEventTree;
113  int run;
114  int subrun;
115  int event;
116  unsigned int c1;
117  unsigned int c2;
118  unsigned int trignum;
119  double eventpurity;
121  double chargepurity;
124  double eventRecoQ;
125  double eventMCQ;
126  double eventdQ;
127  double eventdT;
128  double eventMCC;
129  int tp;
130  int fp;
131  int fn;
132  int tn;
133  double tpc;
134  double fpc;
135  double fnc;
136 
137  TTree * fHitTree;
138  double RecoQ;
139  double MCQ;
140  double RecoT;
141  double MCT;
142  bool foundBoth;
143 
144  // Services needed
148 
149  // Counter position map, as taken from DAQToOffline
150  std::map<unsigned int, std::pair<TVector3, std::vector<TVector3> > > fCounterPositionMap;
151 };
152 
154  : EDAnalyzer(p),
155  fDetProp(lar::providerFrom<detinfo::DetectorPropertiesService>()),
156  fClks(lar::providerFrom<detinfo::DetectorClocksService>())
157 {
158  // Get counter position map for consistent ordering of c1 and c2 numbers
159  DAQToOffline::MakeCounterPositionMap("","counterInformation.txt",fCounterPositionMap,0,0,0);
160 
161  // Read FHICL parameters
162  preampGain = p.get<double>("PreampGainSetting",14.0); // mV/fC
163  AmpToAreaFactor = p.get<double>("AmpToAreaFactor",7.615); // convert amplitude of shaping curve to area of pseudo-gaussian
164  ADCtomV = p.get<double>("ADCtomV",2.808); // ADC/mV, digitization
165  mcscale = p.get<double>("PreviousMCScale");
166  fHitsModuleLabel = p.get<std::string>("HitsModuleLabel","robusthit");
167  fVerbose = p.get<bool>("Verbose",false);
168  fNbins = p.get<int>("NumberBins",22);
169  fCounterT0ModuleLabel = p.get<std::string>("CounterT0ModuleLabel","t0counter");
170 
171  // Initialize channel status service
173 
174  // Initialize histograms
176  hEventPurity = fTfs->make<TH1D>("hEventPurity","Purity of Reco Hit Selection; TP/(TP+FP); # Events",200,0,1.1);
177  hEventEfficiency = fTfs->make<TH1D>("hEventEfficiency","Efficiency of Reco Hit Selection; TP/(TP+FN); # Events",200,0,1.1);
178  hEventChargePurity = fTfs->make<TH1D>("hEventChargePurity","Purity of Reco Hit Charge Selection; ChgTP/(ChgTP+ChgFP); # Events",200,0,1.1);
179  hEventChargeEfficiency = fTfs->make<TH1D>("hEventChargeEfficiency","Efficiency of Reco Hit Charge Selection; ChgTP/(ChgTP+ChgFN); # Events",200,0,1.1);
180  hHitChargeRatio = fTfs->make<TH1D>("hHitChargeRatio","Ratio of reco hit charge to MC hit charge; Reco Charge / MC Charge; # Events",200,0,3);
181  hdQ = fTfs->make<TH1D>("hdQ","; Charge Residual, RecoQ-MCQ; # Events",200,-3000,3000);
182  hChargeComp = fTfs->make<TH2D>("hChargeComp","Comparison of reco and MC charges; MC Charge (fC); Reco Charge (fC)",400,0,30000,400,0,30000);
183  hdT = fTfs->make<TH1D>("hdT","#DeltaT between MC hit and Reco Hit; Reco Hit Time - MC Hit Time (TDC ticks); # Events",200,-30,30);
184  hMCC = fTfs->make<TH1D>("hMCC","Matthew's Correlation Coefficient; MCC; # Events",201,-1.1,1.1);
185 
186  // Make tree to contain bin-by-bin purity and efficiency calculations
187  fHitTree = fTfs->make<TTree>("mcanahits","mcanahits");
188  fHitTree->Branch("run",&run,"run/I");
189  fHitTree->Branch("subrun",&subrun,"subrun/I");
190  fHitTree->Branch("event",&event,"event/I");
191  fHitTree->Branch("c1",&c1,"c1/i");
192  fHitTree->Branch("c2",&c2,"c2/i");
193  fHitTree->Branch("trignum",&trignum,"trignum/i");
194  fHitTree->Branch("RecoQ",&RecoQ,"RecoQ/D");
195  fHitTree->Branch("MCQ",&MCQ,"MCQ/D");
196  fHitTree->Branch("RecoT",&RecoT,"RecoT/D");
197  fHitTree->Branch("MCT",&MCT,"MCT/D");
198  fHitTree->Branch("foundBoth",&foundBoth,"foundBoth/O");
199 
200  // Make tree to contain event-by-event purity and efficiency calculations
201  fEventTree = fTfs->make<TTree>("mcanaevents","mcanaevents");
202  fEventTree->Branch("run",&run,"run/I");
203  fEventTree->Branch("subrun",&subrun,"subrun/I");
204  fEventTree->Branch("event",&event,"event/I");
205  fEventTree->Branch("c1",&c1,"c1/i");
206  fEventTree->Branch("c2",&c2,"c2/i");
207  fEventTree->Branch("trignum",&trignum,"trignum/i");
208  fEventTree->Branch("purity",&eventpurity,"purity/D");
209  fEventTree->Branch("efficiency",&eventefficiency,"efficiency/D");
210  fEventTree->Branch("chargepurity",&chargepurity,"chargepurity/D");
211  fEventTree->Branch("chargeefficiency",&chargeefficiency,"chargeefficiency/D");
212  fEventTree->Branch("chargeratio",&eventchargeratio,"chargeratio/D");
213  fEventTree->Branch("RecoQ",&eventRecoQ,"RecoQ/D");
214  fEventTree->Branch("MCQ",&eventMCQ,"MCQ/D");
215  fEventTree->Branch("dQ",&eventdQ,"dQ/D");
216  fEventTree->Branch("dT",&eventdT,"dT/D");
217  fEventTree->Branch("MCC",&eventMCC,"MCC/D");
218  fEventTree->Branch("mcscale",&mcscale,"mcscale/D");
219  fEventTree->Branch("tp",&tp,"tp/I");
220  fEventTree->Branch("fp",&fp,"fp/I");
221  fEventTree->Branch("fn",&fn,"fn/I");
222  fEventTree->Branch("tn",&tn,"tn/I");
223  fEventTree->Branch("tpc",&tpc,"tpc/D");
224  fEventTree->Branch("fpc",&fpc,"fpc/D");
225  fEventTree->Branch("fnc",&fnc,"fnc/D");
226 }
227 
229 {
230  // Get Services
234 
235  // Get recob::Wire objects to check for dead channels
237  if (!e.getByLabel("caldata",wireHandle)) return;
238 
239  // Get reconstructed hits
241  if (!e.getByLabel(fHitsModuleLabel, hitHandle)) return;
242 
243  // Get all T0 products
245  if (!e.getByLabel(fCounterT0ModuleLabel,t0Handle)) return;
246 
247  // get associated external triggers
248  art::FindManyP<raw::ExternalTrigger> triggers(t0Handle,e,fCounterT0ModuleLabel);
249 
250  // Loop over t0's in this event
251  for (size_t i_t0 = 0; i_t0 < t0Handle->size(); i_t0++)
252  {
253  eventRecoQ = 0;
254  eventMCQ = 0;
255 
256  // Get this anab::T0 object
257  art::Ptr<anab::T0> pt0(t0Handle,i_t0);
258 
259  // Find ExternalTriggers associated with this t0 object
260  std::vector<art::Ptr<raw::ExternalTrigger> > trigvec = triggers.at(i_t0);
261 
262  // Collect all TrigIDs in a vector for processing
263  std::vector<unsigned int> evtTriggers;
264  for (auto const &trig : trigvec) evtTriggers.push_back(trig->GetTrigID());
265 
266  // Fill c1, c2, and trignum variables. Skip if invalid trigger, e.g. incomplete 112 trigger.
267  if (!ValidTrigger(evtTriggers,c1,c2,trignum)) continue;
268 
269  // Make collection for building MCHit objects (note: not the art MCHit objects)
270  std::vector<MCHit> MCHitVec;
271 
272  if (fVerbose) std::cout << "Found " << hitHandle->size() << " recob::Hits in total." << std::endl;
273 
274  // Start searching for true negatives by looking at channels without signal.
275  // Here, start by collecting all kCollection channel numbers
276  std::vector<raw::ChannelID_t> absentChannels;
277  for (raw::ChannelID_t chan = 0; chan < fGeom->Nchannels(); ++chan)
278  {
279  if (fCSP->IsBad(chan)) continue;
280  if (fGeom->SignalType(chan) != geo::kCollection) continue;
281  absentChannels.push_back(chan);
282  }
283 
284  // Remove channels from absentChannels list if it has a recob::Hit
285  for (size_t i_hit = 0; i_hit < hitHandle->size(); ++i_hit)
286  {
287  art::Ptr<recob::Hit> hit(hitHandle,i_hit);
288  std::vector<raw::ChannelID_t>::iterator cit = std::find(absentChannels.begin(),absentChannels.end(),hit->Channel());
289  if (cit != absentChannels.end()) absentChannels.erase(cit);
290  }
291 
292  for (auto sc : bt_serv->SimChannels())
293  {
294  bool channelexists = false;
295  for (size_t i_wire = 0; i_wire < wireHandle->size(); ++i_wire)
296  {
297  art::Ptr<recob::Wire> pwire(wireHandle,i_wire);
298  if (pwire->Channel() == sc->Channel())
299  {
300  channelexists = true;
301  break;
302  }
303  }
304  if (!channelexists) continue;
305 
306  // also remove channels from absentChannels list if it has a Sim Hit
307  if (fCSP->IsBad(sc->Channel())) continue;
308  if (fGeom->SignalType(sc->Channel()) != geo::kCollection) continue;
309  std::vector<raw::ChannelID_t>::iterator cit = std::find(absentChannels.begin(),absentChannels.end(),sc->Channel());
310  if (cit != absentChannels.end()) absentChannels.erase(cit);
311 
312  // also remove channels from absent channels list in the opposite drift volume.
313  //I do this since I can assume there's one track and it can't be on both sides of the APA at the same Z coordinate.
314  //Remember, this is for EW triggers only.
315  std::vector<raw::ChannelID_t>::iterator citopp = std::find(absentChannels.begin(),absentChannels.end(),OppositeTPCChannel(sc->Channel()));
316  if (citopp != absentChannels.end()) absentChannels.erase(citopp);
317 
318  // Initialize a MCHit object for this channel
319  MCHit mchit;
320  auto const& tdcidemap = sc->TDCIDEMap();
321  // Loop over the track id and energies deposited on this channel
322  for (auto const& tdcIt : tdcidemap)
323  {
324  // Get the vector of IDEs
325  auto const& ideVec = tdcIt.second;
326 
327  // Get the TDC (time) of the deposit
328  unsigned short tdc = tdcIt.first;
329 
330  // Loop over IDEs
331  for (auto const& ideIt : ideVec)
332  {
333  // We want only primary muons which cross the detector.
334  // Don't include deltas and other secondary particles because we want to
335  // see how well the reconstruction discounts these other tracks
336  if (abs(ideIt.trackID) != 1) continue;
337  const simb::MCParticle * part = pi_serv->TrackIdToParticle_P(abs(ideIt.trackID));
338  if (part->Mother() != 0) continue;
339 
340  // If the track is a primary muon, then collect this IDE for this channel
341  mchit.idevec.push_back(ideIt);
342 
343  // Sanity check: make sure channel numbers match
344  if (mchit.idevec.size() > 1 && mchit.channel != sc->Channel())
345  throw cet::exception("RobustMCAna") << "Channel IDs don't match!";
346 
347  // Check : if the IDE vector contains different particle codes, the something is weird
348  mchit.channel = sc->Channel();
349  if (mchit.idevec.size() > 1 && mchit.pdg != part->PdgCode())
350  throw cet::exception("RobustMCAna") << "Pdg from previous IDE (" << mchit.pdg << ") doesn't equal this IDE Pdg (" << part->PdgCode() << ")";
351 
352  // Fill the MCHit object, appending energy deposits in the case where more than one IDE exists on the channel
353  // Usually, it's either one or two IDEs per channel with signal. Very rarely more than 2
354  mchit.pdg = part->PdgCode();
355  mchit.particlevec.push_back(part);
356  mchit.tdcvec.push_back(tdc);
357  // Here, adjust the signal size for the MCScale value used in the DataOverlay step
358  // Otherwise, the charges wouldn't make any sense
359  mchit.chargevec.push_back(ideIt.numElectrons*mcscale);
360  }
361  }
362  if (mchit.idevec.size()==0) continue;
363  MCHitVec.push_back(mchit);
364  }
365 
366  // If there are no MCHits and no recob::Hits, then assume an incomplete event,
367  // and don't include it in the tracking efficiency denominator
368  if (MCHitVec.size() == 0 && hitHandle->size() == 0) continue;
369 
370  run = e.run();
371  subrun = e.subRun();
372  event = e.event();
373 
374  // Start dealing with recob::Hits now
375  // recoHitMap.first -> a unique ID for this hit
376  std::map<size_t,art::Ptr<recob::Hit> > recoHitMap;
377  // Collect all recob::Hits in my own format
378  for (size_t i_hit = 0; i_hit < hitHandle->size(); ++i_hit)
379  {
380  art::Ptr<recob::Hit> hit(hitHandle,i_hit);
381  recoHitMap[i_hit] = hit;
382  }
383 
384  // Initialize collections to store various things
385  std::vector<double> chargeratios;
386  std::vector<double> dTs;
387  std::vector<double> dQs;
388  std::vector<art::Ptr<recob::Hit> > recoHits;
389  std::vector<art::Ptr<recob::Hit> > otherwiseHits;
390 
391 
392  // Loop over all MCHits
393  for (auto mchit : MCHitVec)
394  {
395  // Collect information about MCHit
396  raw::ChannelID_t channel = mchit.channel;
397  int numIDEs = mchit.idevec.size();
398  double meanSimTime = TMath::Mean(mchit.tdcvec.begin(),mchit.tdcvec.end(),mchit.chargevec.begin()); // charge weighted mean
399  double sigmaSimTime = TMath::RMS(mchit.tdcvec.begin(),mchit.tdcvec.end(),mchit.chargevec.begin()); // charge weighted RMS
400  double totalSimCharge = std::accumulate(mchit.chargevec.begin(),mchit.chargevec.end(),0);
401  NumElectronsTofC(totalSimCharge); // convert # electrons to fC
402  MCQ = totalSimCharge;
403  fCToSumADC(MCQ);
404  foundBoth = false;
405 
406  // Print information about sim hits
407  if (fVerbose)
408  {
409  std::cout << " Channel: " << channel << ", MeanIDETime: " << meanSimTime << ", RMSTime: " << sigmaSimTime << ", TotalCharge: " << totalSimCharge << ", NumIDEs: " << numIDEs << std::endl;
410  std::cout << "::::::::::IDEs:::::::" << std::endl;
411  for (size_t i = 0; i < mchit.idevec.size(); ++i)
412  {
413  std::cout << " TrackID: " << mchit.idevec[i].trackID << ", numElectrons: " << mchit.chargevec[i] << ", TDC: " << mchit.tdcvec[i] << ", Channel: " << mchit.channel << ", PDG: " << mchit.pdg << std::endl;
414  //std::cout << *mchit.particlevec[i] << std::endl;
415  }
416  }
417 
418  // Print information about recob::Hits
419  if (fVerbose) std::cout << ":::::::::recob::Hits:::::::::" << std::endl;
420  for (auto hit = recoHitMap.begin(); hit != recoHitMap.end(); )
421  {
422  // Bump iterator if recob::Hit is not on the same channel as MCHit
423  if (hit->second->Channel() != channel)
424  {
425  ++hit;
426  continue;
427  }
428  if (fVerbose) std::cout << " Channel: " << hit->second->Channel() << ", PeakTime: " << hit->second->PeakTime() << ", RMS: " << hit->second->RMS() << ", Integral: " << hit->second->Integral() << std::endl;
429 
430  // If the sim hit falls within +/- 1 RMS of the recob::Hit, then consider it a good find
431  if (hit->second->PeakTimePlusRMS() > meanSimTime && hit->second->PeakTimeMinusRMS() < meanSimTime)
432  {
433  // Collect information about the recob::Hit, and the sim Hit
434  foundBoth = true;
435  recoHits.push_back(hit->second);
436  double totalRecoCharge = hit->second->Integral(); // sum ADC
437  RecoQ = totalRecoCharge; // ADC*tick
438  SumADCTofC(totalRecoCharge); // fC
439  double chargeratio = totalRecoCharge / totalSimCharge;
440  RecoT = hit->second->PeakTime();
441  MCT = meanSimTime;
442  double dT = RecoT-MCT;
443  chargeratios.push_back(chargeratio);
444  dTs.push_back(dT);
445  dQs.push_back(RecoQ-MCQ);
446  eventRecoQ += RecoQ;
447  eventMCQ += MCQ;
448 
449  // Fill histograms to compare the reco and MC hits
450  hHitChargeRatio->Fill(chargeratio);
451  hChargeComp->Fill(totalSimCharge,totalRecoCharge); // units of fC
452  hdT->Fill(dT);
453  hdQ->Fill(RecoQ-MCQ);
454 
455  // Remove this reco hit from the map so we can count the recob::Hits left over after associating all sim Hits
456  hit = recoHitMap.erase(hit);
457  }
458  else
459  {
460  otherwiseHits.push_back(hit->second);
461  ++hit;
462  }
463  }
464  fHitTree->Fill();
465 
466  if (fVerbose) std::cout << "::::::::::::::::::::::::::::" << std::endl;
467  }
468 
469  // Calculate stuff and fill TTrees
470 
471  tp = recoHits.size();
472  tn = absentChannels.size();
473  fp = recoHitMap.size();
474  fn = MCHitVec.size()-recoHits.size();
475 
476  eventpurity = Purity( (double)tp, (double)fp );
477  eventefficiency = Efficiency( (double)tp, (double)fn );
478  eventMCC = MCC( (double)tp, (double)fp, (double)fn, (double)tn );
479  eventdT = VMean(dTs);
480  eventchargeratio = VMean(chargeratios);
481  eventdQ = VMean(dQs);
482 
483  //if (fVerbose)
484  {
485  std::cout << "TP: " << tp << " FP: " << fp << " TN: " << tn << " FN: " << fn << std::endl;
486  std::cout << "recoHits.size()=" << tp << " MCHitVec.size()=" << MCHitVec.size() << " otherwiseHits.size()=" << otherwiseHits.size() << std::endl;
487  std::cout << "Purity: " << eventpurity << " Efficiency: " << eventefficiency << std::endl;
488  }
489 
490  // Calculate charge purity and efficiency
491  tpc = 0;
492  for (auto h : recoHits) tpc += h->Integral();
493  SumADCTofC(tpc);
494 
495  fpc = 0;
496  for (auto h : recoHitMap) fpc += h.second->Integral();
497  SumADCTofC(fpc);
498 
499  fnc = 0;
500  for (auto h : MCHitVec) fnc += std::accumulate(h.chargevec.begin(),h.chargevec.end(),0);
501  NumElectronsTofC(fnc); // fC
502  fnc -= tpc;
503 
504  chargepurity = Purity( (double)tpc, (double)fpc );
505  chargeefficiency = Efficiency( (double)tpc, (double)fnc );
506 
507  //if (fVerbose)
508  {
509  std::cout << "TPC: " << tpc << " FPC: " << fpc << " FNC: " << fnc << std::endl;
510  std::cout << "Chg Purity: " << chargepurity << " Chg Efficiency: " << chargeefficiency << std::endl;
511  std::cout << "Event RecoQ: " << eventRecoQ << " MCQ: " << eventMCQ << std::endl;
512  }
513 
514  fEventTree->Fill();
515 
516  // Fill histograms
517  if (eventpurity>=0) hEventPurity->Fill(eventpurity);
521  if (eventMCC>=-1) hMCC->Fill(eventMCC);
522 
523  }
524 }
525 
526 // Calculate purity based on True Positives and False Positives
527 double hit::RobustMCAna::Purity(double tp, double fp)
528 {
529  return (tp+fp<=0) ? -1.0 : tp/(tp+fp);
530 }
531 
532 // Calculate efficiency based on True Positives and False Negatives
533 double hit::RobustMCAna::Efficiency(double tp, double fn)
534 {
535  return (tp+fn<=0) ? -1.0 : tp/(tp+fn);
536 }
537 
538 // Calculate Matthew's Correlation Coefficient
539 // Beware: need True Negatives, but not well defined for this case...
540 double hit::RobustMCAna::MCC(double tp, double fp, double fn, double tn)
541 {
542  return ((tp+fp)*(tp+fn)*(tn+fp)*(tn+fn)<=0) ? -2.0 : ((tp*tn)-(fp*fn))/sqrt((tp+fp)*(tp+fn)*(tn+fp)*(tn+fn));
543 }
544 
545 // Convert Number of electrons to fC
547 {
548  input *= 1.602e-4;
549 }
550 
551 // Convert Sum of ADCs (e.g. from recob::Hit integral) to fC
552 // Use information from electronics shaping and amplification factors
554 {
555  input *= (1/ADCtomV)*(1/(preampGain*AmpToAreaFactor));
556 }
557 
558 // Convert fC to sum of ADCs (e.g. from simulated charge to units used in reco)
560 {
562 }
563 
564 // Robustly calculate the mean of a vector of doubles
565 // If empty, return -999
566 double hit::RobustMCAna::VMean(std::vector<double> v)
567 {
568  return (v.size()==0) ? -999 : TMath::Mean(v.size(),v.data());
569 }
570 
571 // Given a channel number, find the channel number of the wire which is at the
572 // same Z coordinate, but on the opposite side of the APA, in the other drift volume
574 {
576  std::vector<geo::WireID> attachedWires = fGeom->ChannelToWire(chan);
577  for (auto const &w : attachedWires)
578  {
579  geo::TPCID::TPCID_t tpc = w.TPC;
580 
581  if (tpc % 2 == 0) tpc++;
582  else tpc--;
583 
584  geo::WireID wid(w.Cryostat,tpc,w.Plane,w.Wire);
585 
586  raw::ChannelID_t newchan = fGeom->PlaneWireToChannel(wid);
587  return newchan;
588  }
589  return chan;
590 }
591 
592 // Test if this is a valid trigger. Remember: this method is a copy of the method in
593 // RobustHitFinder. If changed in either place, remember to change it in both places.
594 bool hit::RobustMCAna::ValidTrigger(std::vector<unsigned int> evtTriggers, unsigned int & c1arg, unsigned int & c2arg, unsigned int & trignumarg)
595 {
596  c1arg=999; c2arg=999;
597  int contains_111 = 0, contains_112 = 0, contains_113 = 0;
598  int contains_Ntrigs = 0, contains_NU = 0, contains_NL = 0, contains_SU = 0, contains_SL = 0;
599  int contains_EL = 0, contains_WU = 0, contains_TEL = 0;
600  for (size_t i_c = 0; i_c < evtTriggers.size(); i_c++)
601  {
602  unsigned int trigID = evtTriggers[i_c];
603  // for c2: trigID is an unsigned int and always >= 0
604  //if (trigID >= 0 && trigID <= 5) contains_SL++;
605  if (trigID <= 5) contains_SL++;
606  if (trigID >= 6 && trigID <= 15) contains_EL++;
607  if (trigID >= 16 && trigID <= 21) contains_NL++;
608  if (trigID >= 22 && trigID <= 27) contains_NU++;
609  if (trigID >= 28 && trigID <= 37) contains_WU++;
610  if (trigID >= 38 && trigID <= 43) contains_SU++;
611  if (trigID >= 44 && trigID <= 92) contains_TEL++;
612  if (trigID == 111) contains_111++;
613  if (trigID == 112) contains_112++;
614  if (trigID == 113) contains_113++;
615  contains_Ntrigs++;
616  }
617  if (contains_111 + contains_112 + contains_113 != 1) return false; // too many/few coincidences!
618  if (contains_TEL &&
619  (contains_NU || contains_NL || contains_SU || contains_SL || contains_EL || contains_WU)) return false; // track probably doesn't go through detector
620  if (contains_Ntrigs != 3) return false; // too much/little going on!
621  if (contains_111 && (contains_NU || contains_NL || contains_SU || contains_SL)) return false; // 111 should not have NU/NL/SU/SL
622  if (contains_112 && (contains_EL || contains_WU || contains_SU || contains_NL)) return false; // 112 should not have EL/WU/SU/NL
623  if (contains_113 && (contains_EL || contains_WU || contains_NU || contains_SL)) return false; // 113 should not have EL/WU/NU/SL
624  if (contains_111 && (!contains_EL || !contains_WU)) return false; // incomplete trigger
625  if (contains_112 && (!contains_NU || !contains_SL)) return false; // incomplete trigger
626  if (contains_113 && (!contains_SU || !contains_NL)) return false; // incomplete trigger
627 
628  std::vector<unsigned int> counterIDs;
629  trignumarg = 0;
630  for (size_t i_c = 0; i_c < evtTriggers.size(); i_c++)
631  {
632  unsigned int trigID = evtTriggers[i_c];
633  if (trigID >= 44 && trigID <= 100) continue;
634  if (trigID >= 111 && trigID <= 113)
635  {
636  trignumarg = trigID;
637  continue;
638  }
639  counterIDs.push_back(trigID);
640  }
641  if (counterIDs.size() != 2) return false;
642  if (trignumarg == 0) return false;
643 
644  if (trignumarg == 112 || trignumarg == 113)
645  {
646  if (fCounterPositionMap[counterIDs[0]].first.X() > fCounterPositionMap[counterIDs[1]].first.X())
647  {
648  c1arg = counterIDs[0];
649  c2arg = counterIDs[1];
650  }
651  else
652  {
653  c1arg = counterIDs[1];
654  c2arg = counterIDs[0];
655  }
656  }
657  else if (trignumarg == 111)
658  {
659  if (fCounterPositionMap[counterIDs[0]].first.Z() > fCounterPositionMap[counterIDs[1]].first.Z())
660  {
661  c1arg = counterIDs[0];
662  c2arg = counterIDs[1];
663  }
664  else
665  {
666  c1arg = counterIDs[1];
667  c2arg = counterIDs[0];
668  }
669  }
670  if (c1arg == c2arg) return false;
671  if (c1arg == 999 || c2arg == 999) return false;
672 
673  return true;
674 }
675 
virtual bool IsBad(raw::ChannelID_t channel) const =0
Returns whether the specified channel is bad in the current run.
intermediate_table::iterator iterator
std::map< unsigned int, std::pair< TVector3, std::vector< TVector3 > > > fCounterPositionMap
int PdgCode() const
Definition: MCParticle.h:211
std::string fCounterT0ModuleLabel
EventNumber_t event() const
Definition: DataViewImpl.cc:96
std::string string
Definition: nybbler.cc:12
T::provider_type const * providerFrom()
Returns a constant pointer to the provider of specified service.
Definition: ServiceUtil.h:77
const simb::MCParticle * TrackIdToParticle_P(int id) const
int Mother() const
Definition: MCParticle.h:212
Declaration of signal hit object.
std::vector< geo::WireID > ChannelToWire(raw::ChannelID_t const channel) const
Returns a list of wires connected to the specified TPC channel.
void SumADCTofC(double &input)
SigType_t SignalType(geo::PlaneID const &pid) const
Returns the type of signal on the channels of specified TPC plane.
detinfo::DetectorProperties const * fDetProp
EDAnalyzer(fhicl::ParameterSet const &pset)
Definition: EDAnalyzer.h:27
Particle class.
double Efficiency(double tp, double fn)
double MCC(double tp, double fp, double fn, double tn)
unsigned int Nchannels() const
Returns the number of TPC readout channels in the detector.
bool ValidTrigger(std::vector< unsigned int > evtTriggers, unsigned int &c1arg, unsigned int &c2arg, unsigned int &trignumarg)
std::vector< sim::IDE > idevec
T abs(T value)
void NumElectronsTofC(double &input)
bool getByLabel(std::string const &label, std::string const &instance, Handle< PROD > &result) const
Definition: DataViewImpl.h:446
void fCToSumADC(double &input)
const double e
static int input(void)
Definition: code.cpp:15695
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:69
std::vector< const simb::MCParticle * > particlevec
raw::ChannelID_t Channel() const
Returns the ID of the channel (or InvalidChannelID)
Definition: Wire.h:231
double Purity(double tp, double fp)
const lariov::ChannelStatusProvider * fCSP
T get(std::string const &key) const
Definition: ParameterSet.h:231
SubRunNumber_t subRun() const
Definition: DataViewImpl.cc:89
Class providing information about the quality of channels.
General LArSoft Utilities.
Definition: OpFlashAlg.h:15
RunNumber_t run() const
Definition: DataViewImpl.cc:82
Definition of data types for geometry description.
std::vector< unsigned short > tdcvec
Detector simulation of raw signals on wires.
Conversion of times between different formats and references.
Encapsulate the geometry of a wire.
p
Definition: test.py:223
std::vector< double > chargevec
raw::ChannelID_t PlaneWireToChannel(WireID const &wireid) const
Returns the ID of the TPC channel connected to the specified wire.
unsigned int TPCID_t
Type for the ID number.
Definition: geo_types.h:383
double VMean(std::vector< double > v)
LArSoft-specific namespace.
object containing MC truth information necessary for making RawDigits and doing back tracking ...
detinfo::DetectorClocks const * fClks
Interface for experiment-specific channel quality info provider.
raw::ChannelID_t OppositeTPCChannel(raw::ChannelID_t)
RobustMCAna(fhicl::ParameterSet const &p)
const std::vector< art::Ptr< sim::SimChannel > > & SimChannels() const
Declaration of basic channel signal object.
void MakeCounterPositionMap(std::string CounterDir, std::string CounterFile, std::map< unsigned int, std::pair< TVector3, std::vector< TVector3 > > > &CounterPositionMap, double fExtendCountersX=0, double fExtendCountersY=0, double fExtendCountersZ=0)
unsigned int ChannelID_t
Type representing the ID of a readout channel.
Definition: RawTypes.h:27
Interface for experiment-specific service for channel quality info.
RobustMCAna & operator=(RobustMCAna const &)=delete
void analyze(art::Event const &e) override
raw::ChannelID_t Channel() const
ID of the readout channel the hit was extracted from.
Definition: Hit.h:230
Tools and modules for checking out the basics of the Monte Carlo.
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
QTextStream & endl(QTextStream &s)
Event finding and building.
std::string fHitsModuleLabel
h
training ###############################
Definition: train_cnn.py:186
Signal from collection planes.
Definition: geo_types.h:142