All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SpacePointAnalysis_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 #include "canvas/Persistency/Common/FindOneP.h"
13 
15 #include "larcore/CoreUtils/ServiceUtil.h" // lar::providerFrom()
20 
26 
27 // Eigen
28 #include <Eigen/Dense>
29 
30 #include "TH1.h"
31 #include "TH2.h"
32 #include "TProfile.h"
33 #include "TProfile2D.h"
34 #include "TTree.h"
35 
36 #include <cmath>
37 #include <tuple>
38 #include <algorithm>
39 
41 {
42  ////////////////////////////////////////////////////////////////////////
43  //
44  // Class: SpacePointAnalysis
45  // Module Type: producer
46  // File: SpacePointAnalysis.cc
47  //
48  // The intent of this module is to provide methods for
49  // "analyzing" hits on waveforms
50  //
51  // Configuration parameters:
52  //
53  // TruncMeanFraction - the fraction of waveform bins to discard when
54  //
55  // Created by Tracy Usher (usher@slac.stanford.edu) on February 19, 2016
56  //
57  ////////////////////////////////////////////////////////////////////////
58 
59 // The following typedefs will, obviously, be useful
60 using HitPtrVec = std::vector<art::Ptr<recob::Hit>>;
61 using ViewHitMap = std::map<size_t,HitPtrVec>;
62 using TrackViewHitMap = std::map<int,ViewHitMap>;
63 
64 // Define object to keep track of hit related tuple items
66 {
67 public:
68  HitTupleObj() : fTree(nullptr) {}
69 
70  void setBranches(TTree* tree)
71  {
72  tree->Branch("Cryostat", "std::vector<int>", &fCryostatVec);
73  tree->Branch("TPC", "std::vector<int>", &fTPCVec);
74  tree->Branch("TicksTotHit", "std::vector<int>", &fTicksTotHitVec);
75  tree->Branch("Tick", "std::vector<int>", &fTicksVec);
76  tree->Branch("NDF", "std::vector<int>", &fNDFHitVec); //< Number of degrees of freedom of hit fit
77  tree->Branch("Multiplicity", "std::vector<int>", &fMultiplicityHitVec); //< Multiplicity of the snippet the hit is on
78  tree->Branch("LocalIndex", "std::vector<int>", &fLocalIndexHitVec); //< The index of the hit within the snippet
79  tree->Branch("ChiSquare", "std::vector<float>", &fChiSquareHitVec); //< Chi square of fit
80  tree->Branch("SummedADC", "std::vector<float>", &fSummedADCHitVec); //< Sum of all ADC values start/end of snippet
81  tree->Branch("Integral", "std::vector<float>", &fIntegralHitVec); //< Integrated charge +/- n sigma about peak center
82  tree->Branch("PulseHeight", "std::vector<float>", &fPHHitVec); //< Pulse height of hit
83  tree->Branch("RMS", "std::vector<float>", &fRMSHitVec); //< RMS of hit (from fit)
84  tree->Branch("ClusterSize", "std::vector<int>", &fClusterSizeVec); //< Number space points in cluster for this hit
85 
86  fTree = tree;
87 
88  return;
89  }
90 
91  void fill()
92  {
93  if (fTree) fTree->Fill();
94  }
95 
96  void clear()
97  {
98  fCryostatVec.clear();
99  fTPCVec.clear();
100  fTicksTotHitVec.clear();
101  fTicksVec.clear();
102  fNDFHitVec.clear();
103  fMultiplicityHitVec.clear();
104  fLocalIndexHitVec.clear();
105  fChiSquareHitVec.clear();
106  fSummedADCHitVec.clear();
107  fIntegralHitVec.clear();
108  fPHHitVec.clear();
109  fRMSHitVec.clear();
110  fPHOrderHitVec.clear();
111  fClusterSizeVec.clear();
112  }
113 
114  void fillHitInfo(const recob::Hit* hit, int hitWidth, int clusterSize)
115  {
116  fCryostatVec.emplace_back(hit->WireID().Cryostat);
117  fTPCVec.emplace_back(hit->WireID().TPC);
118  fTicksTotHitVec.emplace_back(hitWidth);
119  fTicksVec.emplace_back(hit->PeakTime());
120  fNDFHitVec.emplace_back(hit->DegreesOfFreedom());
121  fMultiplicityHitVec.emplace_back(hit->Multiplicity());
122  fLocalIndexHitVec.emplace_back(hit->LocalIndex());
123  fChiSquareHitVec.emplace_back(hit->GoodnessOfFit());
124  fSummedADCHitVec.emplace_back(hit->SummedADC());
125  fIntegralHitVec.emplace_back(hit->Integral());
126  fPHHitVec.emplace_back(hit->PeakAmplitude());
127  fRMSHitVec.emplace_back(hit->RMS());
128  fClusterSizeVec.emplace_back(clusterSize);
129  }
130 
131  // Define tuple values, these are public so can be diretly accessed for filling
132  std::vector<int> fCryostatVec;
133  std::vector<int> fTPCVec;
134  std::vector<int> fTicksTotHitVec;
135  std::vector<int> fTicksVec;
136  std::vector<int> fNDFHitVec;
137  std::vector<int> fMultiplicityHitVec;
138  std::vector<int> fLocalIndexHitVec;
139  std::vector<float> fChiSquareHitVec;
140  std::vector<float> fSummedADCHitVec;
141  std::vector<float> fIntegralHitVec;
142  std::vector<float> fPHHitVec;
143  std::vector<float> fRMSHitVec;
144 
145  std::vector<int> fPHOrderHitVec;
146  std::vector<int> fClusterSizeVec;
147 
148 private:
149  TTree* fTree;
150 };
151 
152 // Define object to keep track of hit/spacepoint related items
154 {
155 public:
156  HitSpacePointObj() : fTree(nullptr) {}
157 
158  void setBranches(TTree* tree)
159  {
160  tree->Branch("SPCryostat", "std::vector<int>", &fSPCryostatVec);
161  tree->Branch("SPTPC", "std::vector<int>", &fSPTPCVec);
162  tree->Branch("SPQuality", "std::vector<float>", &fSPQualityVec);
163  tree->Branch("SPTotalCharge", "std::vector<float>", &fSPTotalChargeVec);
164  tree->Branch("SPAsymmetry", "std::vector<float>", &fSPAsymmetryVec);
165  tree->Branch("SmallestPH", "std::vector<float>", &fSmallestPHVec);
166  tree->Branch("LargestPH", "std::vector<float>", &fLargestPHVec);
167  tree->Branch("AveragePH", "std::vector<float>", &fAveragePHVec);
168  tree->Branch("LargestDelT", "std::vector<float>", &fLargestDelTVec);
169  tree->Branch("SmallestDelT", "std::vector<float>", &fSmallestDelTVec);
170 
171  tree->Branch("SP_x", "std::vector<float>", &fSP_x);
172  tree->Branch("SP_y", "std::vector<float>", &fSP_y);
173  tree->Branch("SP_z", "std::vector<float>", &fSP_z);
174 
175  tree->Branch("Num2DHits", "std::vector<int>", &fNum2DHitsVec);
176  tree->Branch("NumLongHitsSP", "std::vector<int>", &fNumLongHitsVec);
177  tree->Branch("NumIntersectSet", "std::vector<int>", &fNumIntersectSetVec);
178  tree->Branch("ClusterNSP", "std::vector<int>", &fClusterNSPVec);
179 
180  tree->Branch("HitDeltaT10", "std::vector<float>", &fHitDelta10Vec);
181  tree->Branch("HitSigmaT10", "std::vector<float>", &fHitSigma10Vec);
182  tree->Branch("HitDeltaT21", "std::vector<float>", &fHitDelta21Vec);
183  tree->Branch("HitSigmaT21", "std::vector<float>", &fHitSigma21Vec);
184  tree->Branch("HitDeltaT20", "std::vector<float>", &fHitDelta20Vec);
185  tree->Branch("HitSigmaT20", "std::vector<float>", &fHitSigma20Vec);
186  tree->Branch("HitMultProduct", "std::vector<int>", &fHitMultProductVec);
187 
188  fTree = tree;
189  }
190 
191  void fill()
192  {
193  if (fTree) fTree->Fill();
194  }
195 
196  void clear()
197  {
198  fSPCryostatVec.clear();
199  fSPTPCVec.clear();
200 
201  fSPQualityVec.clear();
202  fSPTotalChargeVec.clear();
203  fSPAsymmetryVec.clear();
204  fSmallestPHVec.clear();
205  fLargestPHVec.clear();
206  fAveragePHVec.clear();
207  fLargestDelTVec.clear();
208  fSmallestDelTVec.clear();
209 
210  fSP_x.clear();
211  fSP_y.clear();
212  fSP_z.clear();
213 
214  fNum2DHitsVec.clear();
215  fNumLongHitsVec.clear();
216  fNumIntersectSetVec.clear();
217  fClusterNSPVec.clear();
218 
219  fHitDelta10Vec.clear();
220  fHitSigma10Vec.clear();
221  fHitDelta21Vec.clear();
222  fHitSigma21Vec.clear();
223  fHitDelta20Vec.clear();
224  fHitSigma20Vec.clear();
225  fHitMultProductVec.clear();
226  }
227 
228  // Define tuple vars, make public for direct access
229  std::vector<int> fSPCryostatVec;
230  std::vector<int> fSPTPCVec;
231 
232  std::vector<float> fSPQualityVec;
233  std::vector<float> fSPTotalChargeVec;
234  std::vector<float> fSPAsymmetryVec;
235  std::vector<float> fSmallestPHVec;
236  std::vector<float> fLargestPHVec;
237  std::vector<float> fAveragePHVec;
238  std::vector<float> fLargestDelTVec;
239  std::vector<float> fSmallestDelTVec;
240 
241  std::vector<float> fSP_x;
242  std::vector<float> fSP_y;
243  std::vector<float> fSP_z;
244 
245  std::vector<int> fNum2DHitsVec;
246  std::vector<int> fNumLongHitsVec;
247  std::vector<int> fNumIntersectSetVec;
248  std::vector<int> fClusterNSPVec;
249 
250  std::vector<float> fHitDelta10Vec;
251  std::vector<float> fHitDelta21Vec;
252  std::vector<float> fHitDelta20Vec;
253  std::vector<float> fHitSigma10Vec;
254  std::vector<float> fHitSigma21Vec;
255  std::vector<float> fHitSigma20Vec;
256  std::vector<int> fHitMultProductVec;
257 
258 private:
259  TTree* fTree;
260 };
261 
262 
263 
265 {
266 public:
267  /**
268  * @brief Constructor
269  *
270  * @param pset
271  */
272  explicit SpacePointAnalysis(fhicl::ParameterSet const & pset);
273 
274  /**
275  * @brief Destructor
276  */
278 
279  // provide for initialization
280  void configure(fhicl::ParameterSet const & pset) override;
281 
282  /**
283  * @brief Interface for initializing the histograms to be filled
284  *
285  * @param TFileService handle to the TFile service
286  * @param string subdirectory to store the hists in
287  */
288  void initializeHists(art::ServiceHandle<art::TFileService>&, const std::string&) override;
289 
290  /**
291  * @brief Interface for initializing the tuple variables
292  *
293  * @param TTree pointer to a TTree object to which to add variables
294  */
295  void initializeTuple(TTree*) override;
296 
297  /**
298  * @brief Interface for method to executve at the end of run processing
299  *
300  * @param int number of events to use for normalization
301  */
302  void endJob(int numEvents) override;
303 
304  /**
305  * @brief Interface for filling histograms
306  */
307  void fillHistograms(const art::Event&) const override;
308 
309 private:
310 
311  // Clear mutable variables
312  void clear() const;
313 
314  void processSpacePoints(const art::Event&, const detinfo::DetectorClocksData&) const;
315 
316  // Relate hits to voxels
317  using HitPointerVec = std::vector<const recob::Hit*>;
318 
319  // Fcl parameters.
320  using PlaneToT0OffsetMap = std::map<geo::PlaneID,float>;
321 
322  std::vector<art::InputTag> fSpacePointLabelVec;
325 
326  // TTree variables
327  mutable TTree* fTree;
328 
329  mutable std::vector<int> fTPCVec;
330  mutable std::vector<int> fCryoVec;
331  mutable std::vector<int> fPlaneVec;
332 
334 
335  using HitTuplebjVec = std::vector<HitTupleObj>;
336 
339 
340  // Useful services, keep copies for now (we can update during begin run periods)
341  const geo::GeometryCore* fGeometry; ///< pointer to Geometry service
342 };
343 
344 //----------------------------------------------------------------------------
345 /// Constructor.
346 ///
347 /// Arguments:
348 ///
349 /// pset - Fcl parameters.
350 ///
351 SpacePointAnalysis::SpacePointAnalysis(fhicl::ParameterSet const & pset) : fTree(nullptr)
352 {
353  fGeometry = lar::providerFrom<geo::Geometry>();
354 
355  configure(pset);
356 
357  // Report.
358  mf::LogInfo("SpacePointAnalysis") << "SpacePointAnalysis configured\n";
359 }
360 
361 //----------------------------------------------------------------------------
362 /// Destructor.
363 SpacePointAnalysis::~SpacePointAnalysis()
364 {}
365 
366 //----------------------------------------------------------------------------
367 /// Reconfigure method.
368 ///
369 /// Arguments:
370 ///
371 /// pset - Fcl parameter set.
372 ///
373 void SpacePointAnalysis::configure(fhicl::ParameterSet const & pset)
374 {
375  fSpacePointLabelVec = pset.get< std::vector<art::InputTag>>("SpacePointLabelVec", {"cluster3d"});
376  fUseT0Offsets = pset.get< bool >("UseT0Offsets", false);
377 
378  return;
379 }
380 
381 //----------------------------------------------------------------------------
382 /// Begin job method.
383 void SpacePointAnalysis::initializeHists(art::ServiceHandle<art::TFileService>& tfs, const std::string& dirName)
384 {
385  // Make a directory for these histograms
386 // art::TFileDirectory dir = tfs->mkdir(dirName.c_str());
387 
388  return;
389 }
390 
391 void SpacePointAnalysis::initializeTuple(TTree* tree)
392 {
393  // Access ART's TFileService, which will handle creating and writing
394  // histograms and n-tuples for us.
395  art::ServiceHandle<art::TFileService> tfs;
396 
397  fTree = tree;
398 
399  fTree->Branch("CryostataVec", "std::vector<int>", &fCryoVec);
400  fTree->Branch("TPCVec", "std::vector<int>", &fTPCVec);
401  fTree->Branch("PlaneVec", "std::vector<int>", &fPlaneVec);
402 
403  // Set up specific branch for space points
404  TTree* locTree = tfs->makeAndRegister<TTree>("SpacePoint_t","SpacePoint Tuple");
405 
407 
408  fHitTupleObjVec.resize(fGeometry->Nplanes());
409 
410  for(size_t plane = 0; plane < fGeometry->Nplanes(); plane++)
411  {
412  // Set up specific branch for space points
413  locTree = tfs->makeAndRegister<TTree>("MatchedHits_P"+std::to_string(plane),"Matched Hits Tuple plane "+std::to_string(plane));
414 
415  fHitTupleObjVec[plane].setBranches(locTree);
416  }
417 
418  clear();
419 
420  return;
421 }
422 
423 void SpacePointAnalysis::clear() const
424 {
425  fTPCVec.clear();
426  fCryoVec.clear();
427  fPlaneVec.clear();
428 
430 
431  for(auto& hitObj : fHitTupleObjVec) hitObj.clear();
432 
433  return;
434 }
435 
436 void SpacePointAnalysis::fillHistograms(const art::Event& event) const
437 {
438  // Ok... this is starting to grow too much and get out of control... we will need to break it up directly...
439 
440  // Always clear the tuple
441  clear();
442 
443  mf::LogDebug("SpacePointAnalysis") << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << std::endl;
444 
445  // Now do the space points
446  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(event);
447  processSpacePoints(event, clockData);
448 
449  // Make sure the output tuples are filled
451 
452  for(auto& hitObj : fHitTupleObjVec) hitObj.fill();
453 
454  return;
455 }
456 
457 void SpacePointAnalysis::processSpacePoints(const art::Event& event,
458  const detinfo::DetectorClocksData& clockData) const
459 {
460  // One time initialization done?
461 
462  // Do the one time initialization of the tick offsets.
463  if (fPlaneToT0OffsetMap.empty())
464  {
465  // Need the detector properties which needs the clocks
466  auto const det_prop = art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(event, clockData);
467 
468  for(size_t cryoIdx = 0; cryoIdx < fGeometry->Ncryostats(); cryoIdx++)
469  {
470  for(size_t tpcIdx = 0; tpcIdx < fGeometry->NTPC(); tpcIdx++)
471  {
472  for(size_t planeIdx = 0; planeIdx < fGeometry->Nplanes(); planeIdx++)
473  {
474  geo::PlaneID planeID(cryoIdx,tpcIdx,planeIdx);
475 
476 // if (fUseT0Offsets) fPlaneToT0OffsetMap[planeID] = int(det_prop.GetXTicksOffset(planeID) - det_prop.GetXTicksOffset(geo::PlaneID(cryoIdx,tpcIdx,0)));
477  if (fUseT0Offsets) fPlaneToT0OffsetMap[planeID] = det_prop.GetXTicksOffset(planeID) - det_prop.GetXTicksOffset(geo::PlaneID(cryoIdx,tpcIdx,0));
478  else fPlaneToT0OffsetMap[planeID] = 0.;
479 
480  std::cout << "--PlaneID: " << planeID << ", has T0 offset: " << fPlaneToT0OffsetMap.find(planeID)->second << std::endl;
481  }
482  }
483  }
484  }
485 
486  // Diagnostics
487  using Triplet = std::tuple<const recob::Hit*, const recob::Hit*, const recob::Hit*>;
488  using TripletMap = std::map<Triplet, std::vector<const recob::SpacePoint*>>;
489 
490  TripletMap tripletMap;
491 
492  // detector properties
493  auto const detProp = art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataForJob();
494 
495  // So now we loop through the various SpacePoint sources
496  for(const auto& collectionLabel : fSpacePointLabelVec)
497  {
498  art::Handle<std::vector<recob::PFParticle>> pfParticleHandle;
499  event.getByLabel(collectionLabel, pfParticleHandle);
500 
501  if (!pfParticleHandle.isValid()) continue;
502 
503  art::Handle< std::vector<recob::SpacePoint>> spacePointHandle;
504  event.getByLabel(collectionLabel, spacePointHandle);
505 
506  if (!spacePointHandle.isValid()) continue;
507 
508  // Recover the collection of associations between tracks and hits
509  art::FindManyP<recob::SpacePoint> pfPartSpacePointAssns(pfParticleHandle, event, collectionLabel);
510 
511  // Look up assocations between pfparticles and space points
512  art::FindManyP<recob::Hit> spHitAssnVec(spacePointHandle, event, collectionLabel);
513 
514  // Use this to build a map between PFParticles and the number of associated space points
515  using PFParticleToNumSPMap = std::map<const recob::PFParticle*,int>;
516 
517  PFParticleToNumSPMap pfParticleToNumSPMap;
518 
519  for(size_t idx = 0; idx < pfParticleHandle->size(); idx++)
520  {
521  art::Ptr<recob::PFParticle> pfParticle(pfParticleHandle,idx);
522 
523  std::vector<art::Ptr<recob::SpacePoint>> spacePointVec(pfPartSpacePointAssns.at(pfParticle.key()));
524 
525  pfParticleToNumSPMap[pfParticle.get()] = spacePointVec.size();
526 
527 // if (spacePointVec.size() > 50000) std::cout << "SpacePointAnalysis finds PFParticle with " << spacePointVec.size() << " associated space points, run/event: " << event.id() << std::endl;
528  }
529 
530  // Ok now we want the reverse look up
531  art::FindManyP<recob::PFParticle> spacePointPFPartAssns(spacePointHandle, event, collectionLabel);
532 
533  std::unordered_map<const recob::Hit*,int> uniqueHitMap;
534 
535  // And now, without further adieu, here we begin the loop that will actually produce some useful output.
536  // Loop over all space points and find out their true nature
537  for(size_t idx = 0; idx < spacePointHandle->size(); idx++)
538  {
539  // Recover space point
540  art::Ptr<recob::SpacePoint> spacePointPtr(spacePointHandle,idx);
541 
542  std::vector<art::Ptr<recob::Hit>> associatedHits(spHitAssnVec.at(spacePointPtr.key()));
543 
544  if (associatedHits.size() < 2)
545  {
546  mf::LogDebug("SpacePointAnalysis") << "I am certain this cannot happen... but here you go, space point with " << associatedHits.size() << " hits" << std::endl;
547  continue;
548  }
549 
550  // Recover the PFParticle associated to this space point and get the number of associated hits
551  int nSpacePointsInPFParticle(0);
552 
553  std::vector<art::Ptr<recob::PFParticle>> pfParticleVec(spacePointPFPartAssns.at(spacePointPtr.key()));
554 
555  if (pfParticleVec.size() == 1) nSpacePointsInPFParticle = pfParticleToNumSPMap.at(pfParticleVec[0].get());
556 
557  mf::LogDebug("SpacePointAnalysis") << "==> pfPartVec size: " << pfParticleVec.size() << ", # space points: " << nSpacePointsInPFParticle << std::endl;
558 
559  // Retrieve the magic numbers from the space point
560  float spQuality = spacePointPtr->Chisq();
561  float spCharge = spacePointPtr->ErrXYZ()[1];
562  float spAsymmetry = spacePointPtr->ErrXYZ()[3];
563  const Double32_t* spPosition = spacePointPtr->XYZ();
564  float smallestPH = std::numeric_limits<float>::max();
565  float largestPH = 0.;
566  int numHits = 0;
567  float averagePH = 0.;
568  float averagePT = 0.;
569  float largestDelT = 0.;
570  float smallestDelT = 100000.;
571  std::vector<float> hitPeakTimeVec = {-10000.,-20000.,-30000.};
572  std::vector<float> hitPeakRMSVec = {1000.,1000.,1000.};
573  int hitMultProduct = 1;
574  int numLongHits(0);
575  int numIntersections(0);
576  int cryostat(-1);
577  int tpc(-1);
578 
579  std::vector<const recob::Hit*> recobHitVec(3,nullptr);
580 
581  std::vector<float> peakAmpVec;
582 
583  // Now we can use our maps to find out if the hits making up the SpacePoint are truly related...
584  for(const auto& hitPtr : associatedHits)
585  {
586  float peakAmplitude = hitPtr->PeakAmplitude();
587  float peakTime = hitPtr->PeakTime();
588  float rms = hitPtr->RMS();
589  int plane = hitPtr->WireID().Plane;
590 
591  peakAmpVec.emplace_back(peakAmplitude);
592 
593  // Add to the set
594  uniqueHitMap[hitPtr.get()] = nSpacePointsInPFParticle;
595 
596  recobHitVec[plane] = hitPtr.get();
597  numHits++;
598  averagePH += peakAmplitude;
599  smallestPH = std::min(peakAmplitude,smallestPH);
600  largestPH = std::max(peakAmplitude,largestPH);
601 
602  hitMultProduct *= hitPtr->Multiplicity();
603 
604  if (hitPtr->DegreesOfFreedom() < 2) numLongHits++;
605 
606  hitPeakTimeVec[plane] = peakTime - fPlaneToT0OffsetMap.find(hitPtr->WireID().planeID())->second;
607  hitPeakRMSVec[plane] = rms;
608  averagePT += hitPeakTimeVec[plane];
609 
610  cryostat = hitPtr->WireID().Cryostat;
611  tpc = hitPtr->WireID().TPC;
612  }
613 
614  Triplet hitTriplet(recobHitVec[0],recobHitVec[1],recobHitVec[2]);
615 
616  tripletMap[hitTriplet].emplace_back(spacePointPtr.get());
617 
618  averagePH /= float(numHits);
619  averagePT /= float(numHits);
620 
621  for(size_t planeIdx = 0; planeIdx < 3; planeIdx++)
622  {
623  // Skip if hit missing
624  if (hitPeakTimeVec[planeIdx] < 0) continue;
625 
626  float delT = hitPeakTimeVec[planeIdx] - averagePT;
627  if (std::abs(delT) > std::abs(largestDelT)) largestDelT = delT;
628  if (std::abs(delT) < std::abs(smallestDelT)) smallestDelT = delT;
629  }
630 
631  // Fill for "all" cases
632  fHitSpacePointObj.fSPCryostatVec.emplace_back(cryostat);
633  fHitSpacePointObj.fSPTPCVec.emplace_back(tpc);
634  fHitSpacePointObj.fSPQualityVec.emplace_back(spQuality);
635  fHitSpacePointObj.fSPTotalChargeVec.emplace_back(spCharge);
636  fHitSpacePointObj.fSPAsymmetryVec.emplace_back(spAsymmetry);
637  fHitSpacePointObj.fSmallestPHVec.emplace_back(smallestPH);
638  fHitSpacePointObj.fLargestPHVec.emplace_back(largestPH);
639  fHitSpacePointObj.fAveragePHVec.emplace_back(averagePH);
640  fHitSpacePointObj.fLargestDelTVec.emplace_back(largestDelT);
641  fHitSpacePointObj.fSmallestDelTVec.emplace_back(smallestDelT);
642  fHitSpacePointObj.fNum2DHitsVec.emplace_back(numHits);
643  fHitSpacePointObj.fNumLongHitsVec.emplace_back(numLongHits);
644  fHitSpacePointObj.fNumIntersectSetVec.emplace_back(numIntersections);
645  fHitSpacePointObj.fClusterNSPVec.emplace_back(nSpacePointsInPFParticle);
646  fHitSpacePointObj.fHitDelta10Vec.emplace_back(hitPeakTimeVec[1] - hitPeakTimeVec[0]);
647  fHitSpacePointObj.fHitSigma10Vec.emplace_back(std::sqrt(std::pow(hitPeakRMSVec[1],2) + std::pow(hitPeakRMSVec[0],2)));
648  fHitSpacePointObj.fHitDelta21Vec.emplace_back(hitPeakTimeVec[2] - hitPeakTimeVec[1]);
649  fHitSpacePointObj.fHitSigma21Vec.emplace_back(std::sqrt(std::pow(hitPeakRMSVec[2],2) + std::pow(hitPeakRMSVec[1],2)));
650  fHitSpacePointObj.fHitDelta20Vec.emplace_back(hitPeakTimeVec[2] - hitPeakTimeVec[0]);
651  fHitSpacePointObj.fHitSigma20Vec.emplace_back(std::sqrt(std::pow(hitPeakRMSVec[2],2) + std::pow(hitPeakRMSVec[0],2)));
652  fHitSpacePointObj.fHitMultProductVec.emplace_back(hitMultProduct);
653 
654  fHitSpacePointObj.fSP_x.emplace_back(spPosition[0]);
655  fHitSpacePointObj.fSP_y.emplace_back(spPosition[1]);
656  fHitSpacePointObj.fSP_z.emplace_back(spPosition[2]);
657  }
658 
659  // Now include hit information for unique hits
660  for(const auto& hitItr : uniqueHitMap)
661  {
662  // Recover hit time range (in ticks), cast a wide net here
663  const recob::Hit* hit = hitItr.first;
664 
665  float peakTime = hit->PeakTime();
666  float rms = hit->PeakTime();
667  int startTick = std::max( 0,int(std::floor(peakTime - 3. * rms)));
668  int endTick = std::min(4096,int(std::ceil( peakTime + 3. * rms)));
669 
670  fHitTupleObjVec[hit->WireID().Plane].fillHitInfo(hit,endTick-startTick+1,hitItr.second);
671 
672  }
673  }
674  // Can we check to see if we have duplicates?
675  std::vector<int> numSpacePointVec = {0,0,0,0,0};
676  for(const auto& tripletPair : tripletMap)
677  {
678  int numSpacePoints = std::min(numSpacePointVec.size()-1,tripletPair.second.size());
679  numSpacePointVec[numSpacePoints]++;
680  }
681  std::cout << "====>> Found " << tripletMap.size() << " SpacePoints, numbers: ";
682  for(const auto& count : numSpacePointVec) std::cout << count << " ";
683  std::cout << std::endl;
684 
685  return;
686 }
687 
688 
689 // Useful for normalizing histograms
690 void SpacePointAnalysis::endJob(int numEvents)
691 {
692  return;
693 }
694 
695 DEFINE_ART_CLASS_TOOL(SpacePointAnalysis)
696 }
short int LocalIndex() const
How well do we believe we know this hit?
Definition: Hit.h:227
Utilities related to art service access.
std::map< int, ViewHitMap > TrackViewHitMap
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.
The data type to uniquely identify a Plane.
Definition: geo_types.h:472
void fillHitInfo(const recob::Hit *hit, int hitWidth, int clusterSize)
int DegreesOfFreedom() const
Definition: Hit.h:229
void initializeHists(art::ServiceHandle< art::TFileService > &, const std::string &) override
Interface for initializing the histograms to be filled.
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:212
Definition of basic raw digits.
float Integral() const
Integral under the calibrated signal waveform of the hit, in tick x ADC units.
Definition: Hit.h:224
process_name hit
Definition: cheaterreco.fcl:51
unsigned int Ncryostats() const
Returns the number of cryostats in the detector.
float GoodnessOfFit() const
Degrees of freedom in the determination of the hit signal shape (-1 by default)
Definition: Hit.h:228
short int Multiplicity() const
How many hits could this one be shared with.
Definition: Hit.h:226
float PeakAmplitude() const
The estimated amplitude of the hit at its peak, in ADC units.
Definition: Hit.h:221
std::vector< art::InputTag > fSpacePointLabelVec
T abs(T value)
void configure(fhicl::ParameterSet const &pset) override
unsigned int Nplanes(unsigned int tpc=0, unsigned int cstat=0) const
Returns the total number of wire planes in the specified TPC.
const geo::GeometryCore * fGeometry
pointer to Geometry service
std::map< size_t, HitPtrVec > ViewHitMap
void endJob(int numEvents) override
Interface for method to executve at the end of run processing.
std::vector< const recob::Hit * > HitPointerVec
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
Description of geometry of one entire detector.
unsigned int NTPC(unsigned int cstat=0) const
Returns the total number of TPCs in the specified cryostat.
void initializeTuple(TTree *) override
Interface for initializing the tuple variables.
float PeakTime() const
Time of the signal peak, in tick units.
Definition: Hit.h:218
std::map< geo::PlaneID, float > PlaneToT0OffsetMap
SpacePointAnalysis(fhicl::ParameterSet const &pset)
Constructor.
Contains all timing reference information for the detector.
void fillHistograms(const art::Event &) const override
Interface for filling histograms.
void processSpacePoints(const art::Event &, const detinfo::DetectorClocksData &) const
std::string to_string(WindowPattern const &pattern)
Interface for experiment-specific channel quality info provider.
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.
std::vector< art::Ptr< recob::Hit >> HitPtrVec
2D representation of charge deposited in the TDC/wire plane
Definition: Hit.h:48
art::ServiceHandle< art::TFileService > tfs
std::size_t count(Cont const &cont)
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:406
Interface for experiment-specific service for channel quality info.
art framework interface to geometry description
BEGIN_PROLOG could also be cout
auto const detProp