All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
HitEfficiencyAnalysis_tool.cc
Go to the documentation of this file.
2 
3 #include "fhiclcpp/ParameterSet.h"
4 #include "art/Utilities/ToolMacros.h"
5 #include "art/Framework/Services/Registry/ServiceHandle.h"
6 #include "art_root_io/TFileService.h"
7 #include "art/Framework/Core/ModuleMacros.h"
8 #include "art_root_io/TFileDirectory.h"
9 #include "messagefacility/MessageLogger/MessageLogger.h"
11 #include "canvas/Persistency/Common/FindManyP.h"
12 
14 #include "larcore/CoreUtils/ServiceUtil.h" // lar::providerFrom()
15 
19 #include "nusimdata/SimulationBase/MCParticle.h"
20 
21 #include "TH1.h"
22 #include "TH2.h"
23 #include "TProfile.h"
24 #include "TProfile2D.h"
25 #include "TTree.h"
26 
27 #include <cmath>
28 #include <algorithm>
29 
31 {
32  ////////////////////////////////////////////////////////////////////////
33  //
34  // Class: HitEfficiencyAnalysis
35  // Module Type: producer
36  // File: HitEfficiencyAnalysis.h
37  //
38  // The intent of this module is to provide methods for
39  // "analyzing" hits on waveforms
40  //
41  // Configuration parameters:
42  //
43  // TruncMeanFraction - the fraction of waveform bins to discard when
44  //
45  // Created by Tracy Usher (usher@slac.stanford.edu) on February 19, 2016
46  //
47  ////////////////////////////////////////////////////////////////////////
48 
49 // The following typedefs will, obviously, be useful
50 using HitPtrVec = std::vector<art::Ptr<recob::Hit>>;
51 using ViewHitMap = std::map<size_t,HitPtrVec>;
52 using TrackViewHitMap = std::map<int,ViewHitMap>;
53 
55 {
56 public:
57  /**
58  * @brief Constructor
59  *
60  * @param pset
61  */
62  explicit HitEfficiencyAnalysis(fhicl::ParameterSet const & pset);
63 
64  /**
65  * @brief Destructor
66  */
68 
69  // provide for initialization
70  void configure(fhicl::ParameterSet const & pset) override;
71 
72  /**
73  * @brief Interface for initializing the histograms to be filled
74  *
75  * @param TFileService handle to the TFile service
76  * @param string subdirectory to store the hists in
77  */
78  void initializeHists(art::ServiceHandle<art::TFileService>&, const std::string&) override;
79 
80  /**
81  * @brief Interface for initializing the tuple variables
82  *
83  * @param TTree pointer to a TTree object to which to add variables
84  */
85  void initializeTuple(TTree*) override;
86 
87  /**
88  * @brief Interface for method to executve at the end of run processing
89  *
90  * @param int number of events to use for normalization
91  */
92  void endJob(int numEvents) override;
93 
94  /**
95  * @brief Interface for filling histograms
96  */
97  void fillHistograms(const art::Event&) const override;
98 
99 private:
100 
101  // Clear mutable variables
102  void clear() const;
103 
104  // The parameters we'll read from the .fcl file.
105  std::vector<art::InputTag> fWireProducerLabelVec;
106  std::vector<art::InputTag> fHitProducerLabelVec;
109  std::string fLocalDirName; ///< Fraction for truncated mean
110  std::vector<unsigned short> fOffsetVec; ///< Allow offsets for each plane
111  std::vector<float> fSigmaVec; ///< Window size for matching to SimChannels
112 
113  // Pointers to the histograms we'll create.
114  std::vector<TH1F*> fTotalElectronsHistVec;
115  std::vector<TH1F*> fMaxElectronsHistVec;
116  std::vector<TH1F*> fHitElectronsVec;
117  std::vector<TH1F*> fHitSumADCVec;
118  std::vector<TH1F*> fHitPulseHeightVec;
119  std::vector<TH1F*> fHitPulseWidthVec;
120  std::vector<TH1F*> fSimNumTDCVec;
121  std::vector<TH1F*> fHitNumTDCVec;
122  std::vector<TH1F*> fNMatchedHitVec;
123  std::vector<TH1F*> fDeltaMidTDCVec;
124  std::vector<TProfile*> fWireEfficVec;
125  std::vector<TProfile*> fWireEfficPHVec;
126  std::vector<TProfile*> fHitEfficVec;
127  std::vector<TProfile*> fHitEfficPHVec;
128  std::vector<TH2F*> fHitVsSimChgVec;
129 
130  std::vector<TH1F*> fNSimChannelHitsVec;
131  std::vector<TH1F*> fNRecobHitVec;
132  std::vector<TH1F*> fHitEfficiencyVec;
133 
134  // TTree variables
135  mutable TTree* fTree;
136 
137  mutable std::vector<int> fTPCVec;
138  mutable std::vector<int> fCryoVec;
139  mutable std::vector<int> fPlaneVec;
140  mutable std::vector<int> fWireVec;
141 
142  mutable std::vector<float> fTotalElectronsVec;
143  mutable std::vector<float> fMaxElectronsVec;
144  mutable std::vector<int> fStartTickVec;
145  mutable std::vector<int> fStopTickVec;
146  mutable int fNMatchedWires;
147  mutable int fNMatchedHits;
148 
149  mutable std::vector<float> fHitPeakTimeVec;
150  mutable std::vector<float> fHitPeakAmpVec;
151  mutable std::vector<float> fHitPeakRMSVec;
152  mutable std::vector<float> fHitBaselinevec;
153  mutable std::vector<float> fHitSummedADCVec;
154  mutable std::vector<float> fHitIntegralVec;
155  mutable std::vector<int> fHitStartTickVec;
156  mutable std::vector<int> fHitStopTickVec;
157 
158  // Useful services, keep copies for now (we can update during begin run periods)
159  const geo::GeometryCore* fGeometry; ///< pointer to Geometry service
160 };
161 
162 //----------------------------------------------------------------------------
163 /// Constructor.
164 ///
165 /// Arguments:
166 ///
167 /// pset - Fcl parameters.
168 ///
169 HitEfficiencyAnalysis::HitEfficiencyAnalysis(fhicl::ParameterSet const & pset) : fTree(nullptr)
170 {
171  fGeometry = lar::providerFrom<geo::Geometry>();
172 
173  configure(pset);
174 
175  // Report.
176  mf::LogInfo("HitEfficiencyAnalysis") << "HitEfficiencyAnalysis configured\n";
177 }
178 
179 //----------------------------------------------------------------------------
180 /// Destructor.
181 HitEfficiencyAnalysis::~HitEfficiencyAnalysis()
182 {}
183 
184 //----------------------------------------------------------------------------
185 /// Reconfigure method.
186 ///
187 /// Arguments:
188 ///
189 /// pset - Fcl parameter set.
190 ///
191 void HitEfficiencyAnalysis::configure(fhicl::ParameterSet const & pset)
192 {
193  fWireProducerLabelVec = pset.get< std::vector<art::InputTag> >("WireModuleLabelVec", std::vector<art::InputTag>() = {"decon1droi"});
194  fHitProducerLabelVec = pset.get< std::vector<art::InputTag> >("HitModuleLabelVec", std::vector<art::InputTag>() = {"gaushit"});
195  fMCParticleProducerLabel = pset.get< std::string >("MCParticleLabel", "largeant");
196  fSimChannelProducerLabel = pset.get< std::string >("SimChannelLabel", "largeant");
197  fLocalDirName = pset.get< std::string >("LocalDirName", std::string("wow"));
198  fOffsetVec = pset.get< std::vector<unsigned short> >("OffsetVec", std::vector<unsigned short>()={0,0,0});
199  fSigmaVec = pset.get< std::vector<float> >("SigmaVec", std::vector<float>()={1.,1.,1.});
200 }
201 
202 //----------------------------------------------------------------------------
203 /// Begin job method.
204 void HitEfficiencyAnalysis::initializeHists(art::ServiceHandle<art::TFileService>& tfs, const std::string& dirName)
205 {
206  // Make a directory for these histograms
207  art::TFileDirectory dir = tfs->mkdir(dirName.c_str());
208 
212  fHitSumADCVec.resize(fGeometry->Nplanes());
215  fSimNumTDCVec.resize(fGeometry->Nplanes());
216  fHitNumTDCVec.resize(fGeometry->Nplanes());
217  fNMatchedHitVec.resize(fGeometry->Nplanes());
218  fDeltaMidTDCVec.resize(fGeometry->Nplanes());
219  fHitVsSimChgVec.resize(fGeometry->Nplanes());
221  fNRecobHitVec.resize(fGeometry->Nplanes());
223 
224  fWireEfficVec.resize(fGeometry->Nplanes());
225  fWireEfficPHVec.resize(fGeometry->Nplanes());
226 
227  fHitEfficVec.resize(fGeometry->Nplanes());
228  fHitEfficPHVec.resize(fGeometry->Nplanes());
229 
230  for(size_t plane = 0; plane < fGeometry->Nplanes(); plane++)
231  {
232  fTotalElectronsHistVec.at(plane) = dir.make<TH1F>(("TotalElecs" + std::to_string(plane)).c_str(), ";# electrons", 250, 0., 100000.);
233  fMaxElectronsHistVec.at(plane) = dir.make<TH1F>(("MaxElecs" + std::to_string(plane)).c_str(), ";# electrons", 250, 0., 20000.);
234  fHitElectronsVec.at(plane) = dir.make<TH1F>(("HitElecs" + std::to_string(plane)).c_str(), ";# electrons", 250, 0., 100000.);
235  fHitSumADCVec.at(plane) = dir.make<TH1F>(("SumADC" + std::to_string(plane)).c_str(), "Sum ADC", 500, 0., 5000.);
236  fHitPulseHeightVec.at(plane) = dir.make<TH1F>(("PulseHeight" + std::to_string(plane)).c_str(), "PH (ADC)", 150, 0., 150.);
237  fHitPulseWidthVec.at(plane) = dir.make<TH1F>(("PulseWidth" + std::to_string(plane)).c_str(), ";RMS", 40, 0., 20.);
238  fSimNumTDCVec.at(plane) = dir.make<TH1F>(("SimNumTDC" + std::to_string(plane)).c_str(), ";TDC ticks", 100, 0., 100.);
239  fHitNumTDCVec.at(plane) = dir.make<TH1F>(("HitNumTDC" + std::to_string(plane)).c_str(), ";TDC ticks", 100, 0., 100.);
240  fNMatchedHitVec.at(plane) = dir.make<TH1F>(("NMatched" + std::to_string(plane)).c_str(), ";# hits", 20, 0., 20.);
241  fDeltaMidTDCVec.at(plane) = dir.make<TH1F>(("DeltaMid" + std::to_string(plane)).c_str(), ";# hits", 50, -25., 25.);
242  fNSimChannelHitsVec.at(plane) = dir.make<TH1F>(("NSimChan" + std::to_string(plane)).c_str(), ";# hits", 300, 0., 1200.);
243  fNRecobHitVec.at(plane) = dir.make<TH1F>(("NRecobHit" + std::to_string(plane)).c_str(), ";# hits", 300, 0., 1200.);
244  fHitEfficiencyVec.at(plane) = dir.make<TH1F>(("PlnEffic" + std::to_string(plane)).c_str(), ";# hits", 101, 0., 1.01);
245 
246  fHitVsSimChgVec.at(plane) = dir.make<TH2F>(("HitVSimQ" + std::to_string(plane)).c_str(), "Sim;Hit", 250, 0., 5000., 250, 0., 100000.);
247 
248  fWireEfficVec.at(plane) = dir.make<TProfile>(("WireEffic" + std::to_string(plane)).c_str(), "Wire Efficiency;# electrons", 200, 0., 100000., 0., 1.);
249  fWireEfficPHVec.at(plane) = dir.make<TProfile>(("WireEfficPH" + std::to_string(plane)).c_str(), "Wire Efficiency;# electrons", 200, 0., 20000., 0., 1.);
250 
251  fHitEfficVec.at(plane) = dir.make<TProfile>(("HitEffic" + std::to_string(plane)).c_str(), "Hit Efficiency;# electrons", 200, 0., 100000., 0., 1.);
252  fHitEfficPHVec.at(plane) = dir.make<TProfile>(("HitEfficPH" + std::to_string(plane)).c_str(), "Hit Efficiency;# electrons", 200, 0., 20000., 0., 1.);
253  }
254 
255  return;
256 }
257 
258 void HitEfficiencyAnalysis::initializeTuple(TTree* tree)
259 {
260  fTree = tree;
261 
262  fTree->Branch("CryostataVec", "std::vector<int>", &fCryoVec);
263  fTree->Branch("TPCVec", "std::vector<int>", &fTPCVec);
264  fTree->Branch("PlaneVec", "std::vector<int>", &fPlaneVec);
265  fTree->Branch("WireVec", "std::vector<int>", &fWireVec);
266 
267  fTree->Branch("TotalElectronsVec", "std::vector<float>", &fTotalElectronsVec);
268  fTree->Branch("MaxElectronsVec", "std::vector<float>", &fMaxElectronsVec);
269  fTree->Branch("StartTick", "std::vector<int>", &fStartTickVec);
270  fTree->Branch("StopTick", "std::vector<int>", &fStopTickVec);
271  fTree->Branch("NMatchedHits", &fNMatchedHits, "NMatchedHits/I");
272  fTree->Branch("NMatchedWires", &fNMatchedWires, "NMatchedWires/I");
273 
274  fTree->Branch("HitPeakTimeVec", "std::vector<float>", &fHitPeakTimeVec);
275  fTree->Branch("HitPeakAmpVec", "std::vector<float>", &fHitPeakAmpVec);
276  fTree->Branch("HitPeakRMSVec", "std::vector<float>", &fHitPeakRMSVec);
277  fTree->Branch("HitBaselineVec", "std::vector<float>", &fHitBaselinevec);
278  fTree->Branch("HitSummedADCVec", "std::vector<float>", &fHitSummedADCVec);
279  fTree->Branch("HitIntegralVec", "std::vector<float>", &fHitIntegralVec);
280  fTree->Branch("HitStartTickVec", "std::vector<float>", &fHitStartTickVec);
281  fTree->Branch("HitStopTickVec", "std::vector<float>", &fHitStopTickVec);
282 
283  clear();
284 
285  return;
286 }
287 
288 void HitEfficiencyAnalysis::clear() const
289 {
290  fTPCVec.clear();
291  fCryoVec.clear();
292  fPlaneVec.clear();
293  fWireVec.clear();
294 
295  fTotalElectronsVec.clear();
296  fMaxElectronsVec.clear();
297  fStartTickVec.clear();
298  fStopTickVec.clear();
299  fNMatchedHits = 0;
300 
301  fHitPeakTimeVec.clear();
302  fHitPeakAmpVec.clear();
303  fHitPeakRMSVec.clear();
304  fHitBaselinevec.clear();
305  fHitSummedADCVec.clear();
306  fHitIntegralVec.clear();
307  fHitStartTickVec.clear();
308  fHitStopTickVec.clear();
309 
310  return;
311 }
312 
313 void HitEfficiencyAnalysis::fillHistograms(const art::Event& event) const
314 {
315  // Basic assumption is that the list of input Wire producers and Hit producers are the same length
316  // and the entries match. Here we check the length
317  if (fWireProducerLabelVec.size() != fHitProducerLabelVec.size()) return;
318 
319  // Recover SimChannel info
320  art::Handle< std::vector<sim::SimChannel>> simChannelHandle;
321  event.getByLabel(fSimChannelProducerLabel, simChannelHandle);
322 
323  // If there is no sim channel informaton then exit
324  if (!simChannelHandle.isValid() || simChannelHandle->empty()) return;
325 
326  // There are several things going on here... for each channel we have particles (track id's) depositing energy in a range to ticks
327  // So... for each channel we want to build a structure that relates particles to tdc ranges and deposited energy (or electrons)
328  // Here is a complicated structure:
329  using TDCToIDEMap = std::map<unsigned short, float>;
330  using ChanToTDCToIDEMap = std::map<raw::ChannelID_t, TDCToIDEMap>;
331  using PartToChanToTDCToIDEMap = std::map<int, ChanToTDCToIDEMap>;
332 
333  PartToChanToTDCToIDEMap partToChanToTDCToIDEMap;
334 
335  // Build out the above data structure
336  for(const auto& simChannel : *simChannelHandle)
337  {
338  for(const auto& tdcide : simChannel.TDCIDEMap())
339  {
340  for(const auto& ide : tdcide.second) partToChanToTDCToIDEMap[ide.trackID][simChannel.Channel()][tdcide.first] = ide.numElectrons;
341  }
342  }
343 
344  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(event);
345 
346  // Loop over entries in the two producer vectors
347  for(size_t tpcID = 0; tpcID < fWireProducerLabelVec.size(); tpcID++)
348  {
349  art::Handle< std::vector<recob::Wire> > wireHandle;
350  event.getByLabel(fWireProducerLabelVec[tpcID], wireHandle);
351 
352  art::Handle< std::vector<recob::Hit> > hitHandle;
353  event.getByLabel(fHitProducerLabelVec[tpcID], hitHandle);
354 
355  art::Handle< std::vector<simb::MCParticle>> mcParticleHandle;
356  event.getByLabel(fMCParticleProducerLabel, mcParticleHandle);
357 
358  if (!wireHandle.isValid() || !hitHandle.isValid() || !mcParticleHandle.isValid()) return;
359 
360  // Find the associations between wire data and hits
361  // What we want to be able to do is look up hits that have been associated to Wire data
362  // So we ask for the list of hits, given a handle to the Wire data and remember that the
363  // associations are made in the hit finder
364  //art::FindManyP<recob::Hit> wireHitAssns(wireHandle,event,fHitProducerLabel);
365 
366  // what needs to be done?
367  // First we should build out a straightforward channel to Wire map so we can look up a given
368  // channel's Wire data as we loop over SimChannels.
369  using ChanToWireMap = std::map<raw::ChannelID_t,const recob::Wire*>;
370 
371  ChanToWireMap channelToWireMap;
372 
373  for(const auto& wire : *wireHandle) channelToWireMap[wire.Channel()] = &wire;
374 
375  // First we should map out all hits by channel so we can easily look up from sim channels
376  // Then go through the sim channels and match hits
377  using ChanToHitVecMap = std::map<raw::ChannelID_t,std::vector<const recob::Hit*>>;
378  ChanToHitVecMap channelToHitVec;
379 
380  for(const auto& hit : *hitHandle) channelToHitVec[hit.Channel()].push_back(&hit);
381 
382  // It is useful to create a mapping between trackID and MCParticle
383  using TrackIDToMCParticleMap = std::map<int, const simb::MCParticle*>;
384 
385  TrackIDToMCParticleMap trackIDToMCParticleMap;
386 
387  for(const auto& mcParticle : *mcParticleHandle) trackIDToMCParticleMap[mcParticle.TrackId()] = &mcParticle;
388 
389  std::vector<int> nSimChannelHitVec = {0,0,0};
390  std::vector<int> nRecobHitVec = {0,0,0};
391 
392  for(const auto& partToChanInfo : partToChanToTDCToIDEMap)
393  {
394  TrackIDToMCParticleMap::const_iterator trackIDToMCPartItr = trackIDToMCParticleMap.find(partToChanInfo.first);
395 
396  if (trackIDToMCPartItr == trackIDToMCParticleMap.end()) continue;
397 
398  int trackPDGCode = trackIDToMCPartItr->second->PdgCode();
399  std::string processName = trackIDToMCPartItr->second->Process();
400 
401  // Looking for primary muons (e.g. CR Tracks)
402  if (fabs(trackPDGCode) != 13 || processName != "primary") continue;
403 
404  for(const auto& chanToTDCToIDEMap : partToChanInfo.second)
405  {
406  TDCToIDEMap tdcToIDEMap = chanToTDCToIDEMap.second;
407  float totalElectrons(0.);
408  float maxElectrons(0.);
409  int nMatchedWires(0);
410  int nMatchedHits(0);
411 
412  // The below try-catch block may no longer be necessary
413  // Decode the channel and make sure we have a valid one
414  std::vector<geo::WireID> wids = fGeometry->ChannelToWire(chanToTDCToIDEMap.first);
415 
416  // Recover plane and wire in the plane
417  unsigned int plane = wids[0].Plane;
418 // unsigned int wire = wids[0].Wire;
419 
420  for(const auto& ideVal : tdcToIDEMap)
421  {
422  totalElectrons += ideVal.second;
423 
424  maxElectrons = std::max(maxElectrons,ideVal.second);
425  }
426 
427  totalElectrons = std::min(totalElectrons, float(99900.));
428 
429  fTotalElectronsHistVec.at(plane)->Fill(totalElectrons, 1.);
430  fMaxElectronsHistVec.at(plane)->Fill(maxElectrons, 1.);
431 
432  nSimChannelHitVec.at(plane)++;
433 
434  unsigned short startTDC = tdcToIDEMap.begin()->first;
435  unsigned short stopTDC = tdcToIDEMap.rbegin()->first;
436 
437  // Convert to ticks to get in same units as hits
438  unsigned short startTick = clockData.TPCTDC2Tick(startTDC) + fOffsetVec.at(plane);
439  unsigned short stopTick = clockData.TPCTDC2Tick(stopTDC) + fOffsetVec.at(plane);
440  unsigned short midTick = (startTick + stopTick) / 2;
441 
442  fSimNumTDCVec.at(plane)->Fill(stopTick - startTick, 1.);
443 
444  // Set up to extract the "best" parameters in the event of more than one hit for this pulse train
445  float nElectronsTotalBest(0.);
446  float hitSummedADCBest(0.);
447  float hitIntegralBest(0.);
448  float hitPeakTimeBest(0.);
449  float hitPeakAmpBest(-100.);
450  float hitRMSBest(0.);
451  float hitBaselineBest(0.);
452  unsigned short hitStopTickBest(0);
453  unsigned short hitStartTickBest(0);
454  unsigned short midHitTickBest(0);
455 
456  // Start by recovering the Wire associated to this channel
457  ChanToWireMap::const_iterator wireItr = channelToWireMap.find(chanToTDCToIDEMap.first);
458 
459  if (wireItr != channelToWireMap.end())
460  {
461  const recob::Wire::RegionsOfInterest_t& signalROI = wireItr->second->SignalROI();
462  const lar::sparse_vector<float>::datarange_t* wireRangePtr(NULL);
463 
464  // Here we need to match the range of the ROI's on the given Wire with the tick range from the SimChannel
465  for(const auto& range : signalROI.get_ranges())
466  {
467  // #################################################
468  // ### Getting a vector of signals for this wire ###
469  // #################################################
470  //std::vector<float> signal(wire->Signal());
471 
472  const std::vector<float>& signal = range.data();
473  raw::TDCtick_t roiFirstBinTick = range.begin_index();
474  raw::TDCtick_t roiLastBinTick = roiFirstBinTick + signal.size();
475 
476  // If no overlap then go to next
477  if (roiFirstBinTick > stopTick || roiLastBinTick < startTick) continue;
478 
479  wireRangePtr = &range;
480  break;
481  }
482 
483  // Check that we have found the wire range
484  if (wireRangePtr)
485  {
486  const recob::Hit* rejectedHit = 0;
487  const recob::Hit* bestHit = 0;
488 
489  nMatchedWires++;
490 
491  // The next mission is to recover the hits associated to this Wire
492  // The easiest way to do this is to simply look up all the hits on this channel and then match
493  ChanToHitVecMap::iterator hitIter = channelToHitVec.find(chanToTDCToIDEMap.first);
494 
495  if (hitIter != channelToHitVec.end())
496  {
497 
498  // Loop through the hits for this channel and look for matches
499  // In the event of more than one hit associated to the sim channel range, keep only
500  // the best match (assuming the nearby hits are "extra")
501  // Note that assumption breaks down for long pulse trains but worry about that later
502  for(const auto& hit : hitIter->second)
503  {
504  unsigned short hitStartTick = hit->PeakTime() - fSigmaVec.at(plane) * hit->RMS();
505  unsigned short hitStopTick = hit->PeakTime() + fSigmaVec.at(plane) * hit->RMS();
506  unsigned short midHitTick = (hitStopTick + hitStartTick) / 2;
507 
508  // If hit is out of range then skip, it is not related to this particle
509  if (hitStartTick > stopTick || hitStopTick < startTick)
510  {
511  if (plane == 1) rejectedHit = hit;
512  continue;
513  }
514 
515  float hitHeight = hit->PeakAmplitude();
516 
517  // Use the hit with the largest pulse height as the "best"
518  if (hitHeight < hitPeakAmpBest) continue;
519 
520  hitPeakAmpBest = hitHeight;
521  bestHit = hit;
522  hitStartTickBest = hitStartTick;
523  hitStopTickBest = hitStopTick;
524  midHitTickBest = midHitTick;
525  }
526 
527  // Find a match?
528  if (bestHit)
529  {
530  nElectronsTotalBest = 0.;
531  hitPeakTimeBest = bestHit->PeakTime();
532  hitIntegralBest = bestHit->Integral();
533  hitSummedADCBest = bestHit->SummedADC();
534  hitRMSBest = bestHit->RMS();
535  hitBaselineBest = 0.; // To do...
536 
537  nMatchedHits++;
538 
539  // Get the number of electrons
540  for(unsigned short tick = hitStartTickBest; tick <= hitStopTickBest; tick++)
541  {
542  unsigned short hitTDC = clockData.TPCTick2TDC(tick - fOffsetVec.at(plane));
543 
544  TDCToIDEMap::iterator ideIterator = tdcToIDEMap.find(hitTDC);
545 
546  if (ideIterator != tdcToIDEMap.end()) nElectronsTotalBest += ideIterator->second;
547  }
548  }
549 
550  if (nMatchedHits > 0)
551  {
552  fHitSumADCVec.at(plane)->Fill(hitSummedADCBest, 1.);
553  fHitVsSimChgVec.at(plane)->Fill(std::min(hitSummedADCBest,float(4999.)), totalElectrons, 1.);
554  fHitPulseHeightVec.at(plane)->Fill(std::min(hitPeakAmpBest,float(149.5)), 1.);
555  fHitPulseWidthVec.at(plane)->Fill(std::min(hitRMSBest,float(19.8)), 1.);
556  fHitElectronsVec.at(plane)->Fill(nElectronsTotalBest, 1.);
557  fHitNumTDCVec.at(plane)->Fill(hitStopTickBest - hitStartTickBest, 1.);
558  fDeltaMidTDCVec.at(plane)->Fill(midHitTickBest - midTick, 1.);
559 
560  nRecobHitVec.at(plane)++;
561  }
562  else if (rejectedHit)
563  {
564  unsigned short hitStartTick = rejectedHit->PeakTime() - fSigmaVec.at(plane) * rejectedHit->RMS();
565  unsigned short hitStopTick = rejectedHit->PeakTime() + fSigmaVec.at(plane) * rejectedHit->RMS();
566 
567  std::cout << "**> TPC: " << rejectedHit->WireID().TPC << ", Plane " << rejectedHit->WireID().Plane << ", wire: " << rejectedHit->WireID().Wire << ", hit start/ stop tick: " << hitStartTick << "/" << hitStopTick << ", start/stop ticks: " << startTick << "/" << stopTick << std::endl;
568  std::cout << " TPC/Plane/Wire: " << wids[0].TPC << "/" << plane << "/" << wids[0].Wire << ", Track # hits: " << partToChanInfo.second.size() << ", # hits: " << hitIter->second.size() << ", # electrons: " << totalElectrons << ", pulse Height: " << rejectedHit->PeakAmplitude() << ", charge: " << rejectedHit->Integral() << ", " << rejectedHit->SummedADC() << std::endl;
569  }
570  else
571  {
572  std::cout << "==> No match, TPC/Plane/Wire: " << "/" << wids[0].TPC << "/" << wids[0].Plane << "/" << wids[0].Wire << ", # electrons: " << totalElectrons << ", startTick: " << startTick << ", stopTick: " << stopTick << std::endl;
573  }
574  }
575  }
576  }
577 
578  fWireEfficVec.at(plane)->Fill(totalElectrons, std::min(nMatchedWires,1), 1.);
579  fWireEfficPHVec.at(plane)->Fill(maxElectrons, std::min(nMatchedWires,1), 1.);
580 
581  fNMatchedHitVec.at(plane)->Fill(nMatchedHits, 1.);
582  fHitEfficVec.at(plane)->Fill(totalElectrons, std::min(nMatchedHits,1), 1.);
583  fHitEfficPHVec.at(plane)->Fill(maxElectrons, std::min(nMatchedHits,1), 1.);
584 
585  // Store tuple variables
586  fTPCVec.push_back(wids[0].TPC);
587  fCryoVec.push_back(wids[0].Cryostat);
588  fPlaneVec.push_back(wids[0].Plane);
589  fWireVec.push_back(wids[0].Wire);
590 
591  fTotalElectronsVec.push_back(totalElectrons);
592  fMaxElectronsVec.push_back(maxElectrons);
593  fStartTickVec.push_back(startTick);
594  fStopTickVec.push_back(stopTick);
595  fNMatchedHits = nMatchedHits;
596  fNMatchedWires = nMatchedWires;
597 
598  fHitPeakTimeVec.push_back(hitPeakTimeBest);
599  fHitPeakAmpVec.push_back(hitPeakAmpBest);
600  fHitPeakRMSVec.push_back(hitRMSBest);
601  fHitBaselinevec.push_back(hitBaselineBest);
602  fHitSummedADCVec.push_back(hitSummedADCBest);
603  fHitIntegralVec.push_back(hitIntegralBest);
604  fHitStartTickVec.push_back(hitStartTickBest);
605  fHitStopTickVec.push_back(hitStopTickBest);
606 
607  }
608  }
609 
610  for(size_t idx = 0; idx < fGeometry->Nplanes();idx++)
611  {
612  if (nSimChannelHitVec.at(idx) > 10)
613  {
614  float hitEfficiency = float(nRecobHitVec.at(idx)) / float(nSimChannelHitVec.at(idx));
615 
616  fNSimChannelHitsVec.at(idx)->Fill(std::min(nSimChannelHitVec.at(idx),1999),1.);
617  fNRecobHitVec.at(idx)->Fill(std::min(nRecobHitVec.at(idx),1999), 1.);
618  fHitEfficiencyVec.at(idx)->Fill(hitEfficiency, 1.);
619  }
620  }
621  }
622 
623  return;
624 }
625 
626 // Useful for normalizing histograms
627 void HitEfficiencyAnalysis::endJob(int numEvents)
628 {
629  return;
630 }
631 
632 DEFINE_ART_CLASS_TOOL(HitEfficiencyAnalysis)
633 }
Utilities related to art service access.
BEGIN_PROLOG true icarus_rawdigitfilter FilterTools FilterPlane1 Plane
geo::WireID WireID() const
Definition: Hit.h:233
float RMS() const
RMS of the hit shape, in tick units.
Definition: Hit.h:220
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.
const range_list_t & get_ranges() const
Returns the internal list of non-void ranges.
float Integral() const
Integral under the calibrated signal waveform of the hit, in tick x ADC units.
Definition: Hit.h:224
WireID_t Wire
Index of the wire within its plane.
Definition: geo_types.h:580
process_name hit
Definition: cheaterreco.fcl:51
void initializeTuple(TTree *) override
Interface for initializing the tuple variables.
std::map< size_t, HitPtrVec > ViewHitMap
const geo::GeometryCore * fGeometry
pointer to Geometry service
std::vector< unsigned short > fOffsetVec
Allow offsets for each plane.
BEGIN_PROLOG TPC
std::vector< float > fSigmaVec
Window size for matching to SimChannels.
float PeakAmplitude() const
The estimated amplitude of the hit at its peak, in ADC units.
Definition: Hit.h:221
int TDCtick_t
Type representing a TDC tick.
Definition: RawTypes.h:25
unsigned int Nplanes(unsigned int tpc=0, unsigned int cstat=0) const
Returns the total number of wire planes in the specified TPC.
std::string fLocalDirName
Fraction for truncated mean.
HitEfficiencyAnalysis(fhicl::ParameterSet const &pset)
Constructor.
tick_as<> tick
Tick number, represented by std::ptrdiff_t.
Definition: electronics.h:75
void initializeHists(art::ServiceHandle< art::TFileService > &, const std::string &) override
Interface for initializing the histograms to be filled.
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
Description of geometry of one entire detector.
void endJob(int numEvents) override
Interface for method to executve at the end of run processing.
tuple dir
Definition: dropbox.py:28
float PeakTime() const
Time of the signal peak, in tick units.
Definition: Hit.h:218
std::string to_string(WindowPattern const &pattern)
std::vector< art::Ptr< recob::Hit >> HitPtrVec
object containing MC truth information necessary for making RawDigits and doing back tracking ...
Range class, with range and data.
float SummedADC() const
The sum of calibrated ADC counts of the hit (0. by default)
Definition: Hit.h:223
Declaration of basic channel signal object.
2D representation of charge deposited in the TDC/wire plane
Definition: Hit.h:48
art::ServiceHandle< art::TFileService > tfs
std::map< int, ViewHitMap > TrackViewHitMap
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:406
void configure(fhicl::ParameterSet const &pset) override
art framework interface to geometry description
BEGIN_PROLOG could also be cout
void fillHistograms(const art::Event &) const override
Interface for filling histograms.