All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TPCPurityMonitor_module.cc
Go to the documentation of this file.
1 // TPCPurityMonitor_module.cc
2 // A basic "skeleton" to read in art::Event records from a file,
3 // access their information, and do something with them.
4 
5 // See
6 // <https://cdcvs.fnal.gov/redmine/projects/larsoftsvn/wiki/Using_the_Framework>
7 // for a description of the ART classes used here.
8 
9 // Almost everything you see in the code below may have to be changed
10 // by you to suit your task. The example task is to make histograms
11 // and n-tuples related to dE/dx of particle tracks in the detector.
12 
13 // As you try to understand why things are done a certain way in this
14 // example ("What's all this stuff about 'auto const&'?"), it will help
15 // to read ADDITIONAL_NOTES.txt in the same directory as this file.
16 
17 #ifndef TPCPurityMonitor_module
18 #define TPCPurityMonitor_module
19 
20 // Framework includes
21 #include "art/Framework/Core/ModuleMacros.h"
22 #include "art/Framework/Core/EDProducer.h"
23 #include "art/Framework/Principal/Event.h"
24 #include "art/Framework/Principal/Handle.h"
25 #include "art/Framework/Services/Registry/ServiceHandle.h"
26 #include "art_root_io/TFileService.h"
27 #include "art_root_io/TFileDirectory.h"
28 #include "art/Utilities/make_tool.h"
29 #include "fhiclcpp/ParameterSet.h"
30 #include "messagefacility/MessageLogger/MessageLogger.h"
32 #include "cetlib/cpu_timer.h"
33 
34 // LArSoft includes
36 #include "larcore/CoreUtils/ServiceUtil.h" // lar::providerFrom()
42 
43 #include "lardataobj/RawData/raw.h"
51 
52 // One really does not like root but one has to use it
53 #include "TTree.h"
54 
55 //purity info class
57 
58 // Eigen includes
59 #include "Eigen/Core"
60 #include "Eigen/Dense"
61 #include "Eigen/Eigenvalues"
62 #include "Eigen/Geometry"
63 #include "Eigen/Jacobi"
64 
65 // C++ Includes
66 #include <vector>
67 #include <algorithm>
68 #include <numeric>
69 #include <functional>
70 #include <tuple>
71 
73 {
74 //-----------------------------------------------------------------------
75 //-----------------------------------------------------------------------
76 // class definition
77 
78 class TPCPurityMonitor : public art::EDProducer
79 {
80 public:
81 
82  // Standard constructor and destructor for an ART module.
83  explicit TPCPurityMonitor(fhicl::ParameterSet const& pset);
84  virtual ~TPCPurityMonitor();
85 
86  // This method is called once, at the start of the job. In this
87  // example, it will define the histograms and n-tuples we'll write.
88  void beginJob();
89  void endJob();
90 
91  // This method is called once, at the start of each run. It's a
92  // good place to read databases or files that may have
93  // run-dependent information.
94  // void beginRun(const art::Run& run);
95 
96  // The analysis routine, called once per event.
97  void produce(art::Event& evt);
98 
99 private:
100  // Define a data structure to keep track of a hit's meta data
101  using HitMetaPair = std::pair<art::Ptr<recob::Hit>,const recob::TrackHitMeta*>;
102  using HitMetaPairVec = std::vector<HitMetaPair>;
103 
104  // Define the basic data structure we will use
105  using StatusChargePair = std::pair<bool,double>;
106  using HitStatusChargePair = std::pair<HitMetaPair,StatusChargePair>;
107  using HitStatusChargePairVec = std::vector<HitStatusChargePair>;
108 
109  // We would also like to keep tracy of the trajectory points along the track
110  using PointDirTuple = std::tuple<geo::Point_t,geo::Vector_t,geo::Vector_t>;
111  using HitPointDirTupleMap = std::unordered_map<const recob::Hit*,PointDirTuple>;
112 
113  // We also need to define a container for the output of the 2D PCA Analysis
115  {
116  public:
117 
118  using EigenValues = Eigen::Vector2d;
119  using EigenVectors = Eigen::Matrix2d;
120 
122  fSVD_OK(false), fNumHitsUsed(0), fEigenValues(EigenValues::Zero()), fEigenVectors(EigenVectors::Zero()), fAvePosition(Eigen::Vector2d::Zero()) {}
123 
124  PrincipalComponents2D(bool ok, int nHits, const EigenValues& eigenValues, const EigenVectors& eigenVecs, const Eigen::Vector2d& avePos) :
125  fSVD_OK(ok), fNumHitsUsed(nHits), fEigenValues(eigenValues), fEigenVectors(eigenVecs), fAvePosition(avePos) {}
126 
127  bool getSvdOK() const {return fSVD_OK;}
128  int getNumHitsUsed() const {return fNumHitsUsed;}
129  const EigenValues& getEigenValues() const {return fEigenValues;}
130  const EigenVectors& getEigenVectors() const {return fEigenVectors;}
131  const Eigen::Vector2d& getAvePosition() const {return fAvePosition;}
132  void flipAxis(size_t axis) { fEigenVectors.row(axis) = -fEigenVectors.row(axis);}
133 
134  private:
135 
136  bool fSVD_OK; ///< SVD Decomposition was successful
137  int fNumHitsUsed; ///< Number of hits in the decomposition
138  EigenValues fEigenValues; ///< Eigen values from SVD decomposition
139  EigenVectors fEigenVectors; ///< The three principle axes
140  Eigen::Vector2d fAvePosition; ///< Average position of hits fed to PCA
141  };
142 
143  // We also need to define a container for the output of the 2D PCA Analysis
145  {
146  public:
147 
148  using EigenValues = Eigen::Vector3d;
149  using EigenVectors = Eigen::Matrix3d;
150 
152  fSVD_OK(false), fNumHitsUsed(0), fEigenValues(EigenValues::Zero()), fEigenVectors(EigenVectors::Zero()), fAvePosition(Eigen::Vector3d::Zero()) {}
153 
154  PrincipalComponents3D(bool ok, int nHits, const EigenValues& eigenValues, const EigenVectors& eigenVecs, const Eigen::Vector3d& avePos) :
155  fSVD_OK(ok), fNumHitsUsed(nHits), fEigenValues(eigenValues), fEigenVectors(eigenVecs), fAvePosition(avePos) {}
156 
157  bool getSvdOK() const {return fSVD_OK;}
158  int getNumHitsUsed() const {return fNumHitsUsed;}
159  const EigenValues& getEigenValues() const {return fEigenValues;}
160  const EigenVectors& getEigenVectors() const {return fEigenVectors;}
161  const Eigen::Vector3d& getAvePosition() const {return fAvePosition;}
162  void flipAxis(size_t axis) { fEigenVectors.row(axis) = -fEigenVectors.row(axis);}
163 
164  private:
165 
166  bool fSVD_OK; ///< SVD Decomposition was successful
167  int fNumHitsUsed; ///< Number of hits in the decomposition
168  EigenValues fEigenValues; ///< Eigen values from SVD decomposition
169  EigenVectors fEigenVectors; ///< The three principle axes
170  Eigen::Vector3d fAvePosition; ///< Average position of hits fed to PCA
171  };
172 
173  // This method reads in any parameters from the .fcl files. This
174  // method is called 'reconfigure' because it might be called in the
175  // middle of a job; e.g., if the user changes parameter values in an
176  // interactive event display.
177  void reconfigure(fhicl::ParameterSet const& pset);
178 
179  // Compute the principle axes
180  void GetPrincipalComponents2D(const HitStatusChargePairVec& hitPairVector, PrincipalComponents2D& pca) const;
182 
183  // Reject outliers
184  void RejectOutliers(HitStatusChargePairVec& hitPairVector, const PrincipalComponents2D& pca) const;
185 
186  // The following typedefs will, obviously, be useful
187  double length(const recob::Track* track);
188 
189  double projectedLength(const recob::Track* track);
190 
191  // The parameters we'll read from the .fcl file.
192  std::vector<art::InputTag> fTrackLabelVec; ///< labels for source of tracks
193  unsigned fSelectedPlane; ///< Select hits from this plane
194  unsigned fMinNumHits; ///< Minimum number of hits
195  float fMinTickRange; ///< Require track to span some number of ticks
196  float fAssumedELifetime; ///< Lifetime assumed for calculation
197  float fMinRejectFraction; ///< Reject this fraction of "low Q" hits
198  float fMaxRejectFraction; ///< Reject this fraction of "high Q" hits
199  float fOutlierRejectFrac; ///< Fraction of outliers to reject
200  bool fUseHitIntegral; ///< Setting to false swaps to "SummedADC"
201  bool fWeightByChiSq; ///< Weight the PCA by the hit chisquare
202  bool fDiagnosticTuple; ///< Output the diagnostic tuple
203 
204  float fSamplingRate; ///< Recover the sampling rate from the clock data
205 
206  // Output tuple variables
207  int fRunNumber; ///< run number this event
208  int fSubRunNumber; ///< sub run number this event
209  int fEventNumber; ///< event number this event
210  int fCryostat; ///< Cryostat for given track
211  int fTPC; ///< TPC for given track
212  int fTrackIdx; ///< index of track
213  int fWireRange; ///< Last - first wire number
214  int fWires; ///< Number wires spanned
215  int fTicks; ///< Number ticks spanned
216  double fAttenuation; ///< Attenuation from calc
217  double fError; ///< Error from calc
218  std::vector<double> fTrackStartXVec; ///< Starting x position of track
219  std::vector<double> fTrackStartYVec; ///< Starting y position of track
220  std::vector<double> fTrackStartZVec; ///< Starting z position of track
221  std::vector<double> fTrackDirXVec; ///< Starting x direction of track
222  std::vector<double> fTrackDirYVec; ///< Starting x direction of track
223  std::vector<double> fTrackDirZVec; ///< Starting x direction of track
224  std::vector<double> fTrackEndXVec; ///< Ending x position of track
225  std::vector<double> fTrackEndYVec; ///< Ending y position of track
226  std::vector<double> fTrackEndZVec; ///< Ending z position of track
227  std::vector<double> fTrackEndDirXVec; ///< Ending x direction of track
228  std::vector<double> fTrackEndDirYVec; ///< Ending x direction of track
229  std::vector<double> fTrackEndDirZVec; ///< Ending x direction of track
230  std::vector<double> fPCAAxes2D; ///< Axes for PCA
231  std::vector<double> fEigenValues2D; ///< Eigen values
232  std::vector<double> fMeanPosition2D; ///< Mean position used for PCA
233  std::vector<double> fPCAAxes3D; ///< Axes for PCA 3D
234  std::vector<double> fEigenValues3D; ///< Eigen values 3D
235  std::vector<double> fMeanPosition3D; ///< Mean position used for PCA
236  std::vector<double> fTickVec; ///< vector of ticks
237  std::vector<double> fChargeVec; ///< vector of hit charges
238  std::vector<double> fDeltaXVec; ///< Keep track of hits path length from track fit
239  std::vector<double> fGoodnessOfFitVec; ///< Goodness of the hit's fit
240  std::vector<int> fDegreesOfFreeVec; ///< Degrees of freedom
241  std::vector<int> fSnippetLengthVec; ///< Lenght from start/end of hit
242  std::vector<bool> fGoodHitVec; ///< Hits were considered good
243  std::vector<double> fCosThetaYZ; ///< cos(thetaYZ) hit trajector to wire
244 
245  TTree* fDiagnosticTree; ///< Pointer to our tree
246 
248 
249  // Other variables that will be shared between different methods.
250  const geo::GeometryCore* fGeometry; // pointer to Geometry service
251 }; // class TPCPurityMonitor
252 
253 // This macro has to be defined for this module to be invoked from a
254 // .fcl file; see TPCPurityMonitor.fcl for more information.
255 DEFINE_ART_MODULE(TPCPurityMonitor)
256 
257 //-----------------------------------------------------------------------
258 //-----------------------------------------------------------------------
259 // class implementation
260 
261 //-----------------------------------------------------------------------
262 // Constructor
263 TPCPurityMonitor::TPCPurityMonitor(fhicl::ParameterSet const& parameterSet)
264  : EDProducer{parameterSet},
265  fDiagnosticTree(nullptr),
266  fNumEvents(0)
267 
268 {
269  fGeometry = lar::providerFrom<geo::Geometry>();
270 
271  // We're going to output purity objects
272  produces<std::vector<anab::TPCPurityInfo>>("",art::Persistable::Yes);
273 
274  // Read in the parameters from the .fcl file.
275  this->reconfigure(parameterSet);
276 }
277 
278 //-----------------------------------------------------------------------
279 // Destructor
280 TPCPurityMonitor::~TPCPurityMonitor()
281 {}
282 
283 //-----------------------------------------------------------------------
284 void TPCPurityMonitor::beginJob()
285 {
286  // Get the detector length, to determine the maximum bin edge of one
287  // of the histograms.
288  //double detectorLength = fGeometry->DetLength();
289 
290  // Access ART's TFileService, which will handle creating and writing
291  // histograms and n-tuples for us.
292  if (fDiagnosticTuple)
293  {
294  art::ServiceHandle<art::TFileService> tfs;
295 
296  fDiagnosticTree = tfs->make<TTree>("PurityMonitor","");
297 
298  fDiagnosticTree->Branch("run", &fRunNumber, "run/I");
299  fDiagnosticTree->Branch("subrun", &fSubRunNumber, "subrun/I");
300  fDiagnosticTree->Branch("event", &fEventNumber, "event/I");
301  fDiagnosticTree->Branch("cryostat", &fCryostat, "cryostat/I");
302  fDiagnosticTree->Branch("tpc", &fTPC, "tpc/I");
303  fDiagnosticTree->Branch("trackidx", &fTrackIdx, "trackidx/I");
304  fDiagnosticTree->Branch("wirerange", &fWireRange, "wirerange/I");
305  fDiagnosticTree->Branch("nwires", &fWires, "nwires/I");
306  fDiagnosticTree->Branch("nticks", &fTicks, "nticks/I");
307  fDiagnosticTree->Branch("attenuation", &fAttenuation, "attenuation/D");
308  fDiagnosticTree->Branch("error", &fError, "error/D");
309 
310  fDiagnosticTree->Branch("trkstartx", "std::vector<double>", &fTrackStartXVec);
311  fDiagnosticTree->Branch("trkstarty", "std::vector<double>", &fTrackStartYVec);
312  fDiagnosticTree->Branch("trkstartz", "std::vector<double>", &fTrackStartZVec);
313  fDiagnosticTree->Branch("trkdirx", "std::vector<double>", &fTrackDirXVec);
314  fDiagnosticTree->Branch("trkdiry", "std::vector<double>", &fTrackDirYVec);
315  fDiagnosticTree->Branch("trkdirz", "std::vector<double>", &fTrackDirZVec);
316  fDiagnosticTree->Branch("trkendx", "std::vector<double>", &fTrackEndXVec);
317  fDiagnosticTree->Branch("trkendy", "std::vector<double>", &fTrackEndYVec);
318  fDiagnosticTree->Branch("trkendz", "std::vector<double>", &fTrackEndZVec);
319  fDiagnosticTree->Branch("trkenddirx", "std::vector<double>", &fTrackEndDirXVec);
320  fDiagnosticTree->Branch("trkenddiry", "std::vector<double>", &fTrackEndDirYVec);
321  fDiagnosticTree->Branch("trkenddirz", "std::vector<double>", &fTrackEndDirZVec);
322  fDiagnosticTree->Branch("pcavec2d", "std::vector<double>", &fPCAAxes2D);
323  fDiagnosticTree->Branch("eigenvec2d", "std::vector<double>", &fEigenValues2D);
324  fDiagnosticTree->Branch("meanpos2d", "std::vector<double>", &fMeanPosition2D);
325  fDiagnosticTree->Branch("pcavec3d", "std::vector<double>", &fPCAAxes3D);
326  fDiagnosticTree->Branch("eigenvec3d", "std::vector<double>", &fEigenValues3D);
327  fDiagnosticTree->Branch("meanpos3d", "std::vector<double>", &fMeanPosition3D);
328  fDiagnosticTree->Branch("tickvec", "std::vector<double>", &fTickVec);
329  fDiagnosticTree->Branch("chargevec", "std::vector<double>", &fChargeVec);
330  fDiagnosticTree->Branch("deltaxvec", "std::vector<double>", &fDeltaXVec);
331  fDiagnosticTree->Branch("goodnessvec", "std::vector<double>", &fGoodnessOfFitVec);
332  fDiagnosticTree->Branch("freedomvec", "std::vector<int>", &fDegreesOfFreeVec);
333  fDiagnosticTree->Branch("snippetvec", "std::vector<int>", &fSnippetLengthVec);
334  fDiagnosticTree->Branch("goodhitvec", "std::vector<bool>", &fGoodHitVec);
335  fDiagnosticTree->Branch("costhetaYZ", "std::vector<double>", &fCosThetaYZ);
336  }
337 
338 
339  // zero out the event counter
340  fNumEvents = 0;
341 }
342 
343 //-----------------------------------------------------------------------
344 //void TPCPurityMonitor::beginRun(const art::Run& /*run*/)
345 //{
346  // How to convert from number of electrons to GeV. The ultimate
347  // source of this conversion factor is
348  // ${LARSIM_DIR}/include/SimpleTypesAndConstants/PhysicalConstants.h.
349 // art::ServiceHandle<sim::LArG4Parameters> larParameters;
350 // fElectronsToGeV = 1./larParameters->GeVToElectrons();
351 //}
352 
353 //-----------------------------------------------------------------------
354 void TPCPurityMonitor::reconfigure(fhicl::ParameterSet const& p)
355 {
356  // Read parameters from the .fcl file. The names in the arguments
357  // to p.get<TYPE> must match names in the .fcl file.
358  fTrackLabelVec = p.get< std::vector<art::InputTag> >("TrackLabel", {""});
359  fSelectedPlane = p.get< unsigned >("SelectedPlane", 2);
360  fMinNumHits = p.get< unsigned >("MinNumHits", 100);
361  fMinTickRange = p.get< float >("MinTickRange", 150.);
362  fAssumedELifetime = p.get< float >("AssumedELifetime", 600000.);
363  fMinRejectFraction = p.get< float >("MinRejectFraction", 0.05);
364  fMaxRejectFraction = p.get< float >("MaxRejectFraction", 0.95);
365  fOutlierRejectFrac = p.get< float >("OutlierRejectFrac", 0.70);
366  fUseHitIntegral = p.get< bool >("UseHitIntegral", true);
367  fWeightByChiSq = p.get< bool >("WeightByChiSq", false);
368  fDiagnosticTuple = p.get< bool >("DiagnosticTuple", true);
369 
370  return;
371 }
372 
373 //-----------------------------------------------------------------------
374 void TPCPurityMonitor::produce(art::Event& event)
375 {
376  //setup output vector#include "lardataobj/RecoBase/TrackHitMeta.h"
377  std::unique_ptr< std::vector<anab::TPCPurityInfo> > outputPtrVector(new std::vector<anab::TPCPurityInfo>());
378 
379  fNumEvents++;
380 
381  // Recover the detector properties.
382  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(event);
383 
384  fSamplingRate = 1.e-3 * sampling_rate(clockData); // Note sampling rate is in ns, convert to us
385 
386  for(const auto& trackLabel : fTrackLabelVec)
387  {
388  // Make a pass through all hits to make contrasting plots
389  art::Handle< std::vector<recob::Track>> trackHandle;
390  event.getByLabel(trackLabel, trackHandle);
391 
392  if (!trackHandle.isValid()) continue;
393 
394  // I don't know another way to do this... but we need to build a map from hit to spacepoint
395  // since we don't seem to have a way to go that direction with what we have for kalman fit
396  // tracks.
397  using HitToSpacePointMap = std::unordered_map<const recob::Hit*,const recob::SpacePoint*>;
398 
399  HitToSpacePointMap hitToSpacePointMap;
400 
401  using PointCloud = std::vector<geo::Point_t>;
402 
403  PointCloud pointCloud;
404 
405  // Recover the collection of associations between tracks and hits and hits and spacepoints
406  art::FindManyP<recob::Hit,recob::TrackHitMeta> trackHitAssns(trackHandle, event, trackLabel);
407 
408  // Loop over tracks and recover hits
409  for(size_t trackIdx = 0; trackIdx < trackHandle->size(); trackIdx++)
410  {
411  art::Ptr<recob::Track> track(trackHandle,trackIdx);
412 
413  const std::vector<art::Ptr<recob::Hit>>& trackHitsVec(trackHitAssns.at(track.key()));
414  const std::vector<const recob::TrackHitMeta*> metaHitsVec = trackHitAssns.data(track.key());
415 
416  // Focus on selected hits:
417  // 1) Pick out hits on a single plane given by fhicl parameter
418  // 2) multiplicity == 1 which should give us clean gaussian shaped pulses
419  using TPCToHitMetaPairVecMap = std::unordered_map<unsigned int,HitMetaPairVec>;
420 
421  TPCToHitMetaPairVecMap selectedHitMetaVecMap;
422 
423  for(size_t idx=0; idx<trackHitsVec.size(); idx++)
424  {
425  art::Ptr<recob::Hit> hit(trackHitsVec.at(idx));
426 
427  if (hit->WireID().Plane == fSelectedPlane && hit->Multiplicity() == 1) selectedHitMetaVecMap[hit->WireID().TPC].emplace_back(hit,metaHitsVec.at(idx));
428  }
429 
430  if (selectedHitMetaVecMap.empty()) continue;
431 
432  // Currently we need to limit the analysis to a single TPC and we have tracks which may have been stitched across the cathode...
433  // For now, we search and find the TPC with the most hits
434  TPCToHitMetaPairVecMap::iterator bestMapItr = selectedHitMetaVecMap.begin();
435 
436  for(TPCToHitMetaPairVecMap::iterator mapItr = selectedHitMetaVecMap.begin(); mapItr != selectedHitMetaVecMap.end(); mapItr++)
437  {
438  if (mapItr->second.size() > bestMapItr->second.size()) bestMapItr = mapItr;
439  }
440 
441  HitMetaPairVec& selectedHitMetaVec = bestMapItr->second;
442 
443  // Need a minimum number of hits
444  if (selectedHitMetaVec.size() < fMinNumHits) continue;
445 
446  // Sort hits by increasing time
447  std::sort(selectedHitMetaVec.begin(),selectedHitMetaVec.end(),[](const auto& left, const auto& right){return left.first->PeakTime() < right.first->PeakTime();});
448 
449  // Require track to have a minimum range in ticks
450  if (selectedHitMetaVec.back().first->PeakTime() - selectedHitMetaVec.front().first->PeakTime() < fMinTickRange) continue;
451 
452  // At this point we should have a vector of art::Ptrs to hits on the selected plane
453  // So we should be able to now transition to computing the attenuation
454  // Start by forming a vector of pairs of the time (in ticks) and the ln of charge derated by an assumed lifetime
455  HitStatusChargePairVec hitStatusChargePairVec;
456  HitPointDirTupleMap hitPointDirTupleMap;
457 
458  float firstHitTime(selectedHitMetaVec.front().first->PeakTime());
459  double maxDeltaX(1.5); // Assume a "long hit" would be no more than 1.5 cm in length
460  double wirePitch(0.3);
461 
462  for(const auto& hitMetaPair: selectedHitMetaVec)
463  {
464  unsigned int trkHitIndex = hitMetaPair.second->Index();
465  double deltaX = 0.3; // Set this to 3 mm just in case no corresponding point
466  double cosTheta = -100.;
467 
468  if (trkHitIndex != std::numeric_limits<unsigned int>::max() && track->HasValidPoint(trkHitIndex))
469  {
470  geo::Point_t hitPos = track->LocationAtPoint(trkHitIndex);
471  geo::Vector_t hitDir = track->DirectionAtPoint(trkHitIndex);
472  const geo::WireGeo& wireGeo = fGeometry->Wire(hitMetaPair.first->WireID());
473  geo::Vector_t wireDir(wireGeo.Direction()[0],wireGeo.Direction()[1],wireGeo.Direction()[2]);
474 
475  pointCloud.emplace_back(hitPos);
476 
477  cosTheta = std::abs(hitDir.Dot(wireDir));
478 
479  if (cosTheta < 1.)
480  {
481  deltaX = std::min(wirePitch / (1. - cosTheta), maxDeltaX);
482  }
483  else deltaX = maxDeltaX;
484 
485  double charge = fUseHitIntegral ? hitMetaPair.first->Integral() : hitMetaPair.first->SummedADC();
486 
487  hitStatusChargePairVec.emplace_back(hitMetaPair,StatusChargePair(true,charge/deltaX));
488  hitPointDirTupleMap[hitMetaPair.first.get()] = PointDirTuple(hitPos,hitDir,wireDir);
489  }
490  }
491 
492  size_t numOrig = hitStatusChargePairVec.size();
493  size_t lowCutIdx = fMinRejectFraction * numOrig;
494  size_t hiCutIdx = fMaxRejectFraction * numOrig;
495 
496  // Will require a minimum number of hits left over to proceed
497  if (lowCutIdx + 10 >= hiCutIdx)
498  {
499  std::cout << "*****>>>> lowCutIdx >= hiCutIdx: " << lowCutIdx << ", " << hiCutIdx << std::endl;
500  continue;
501  }
502 
503 // HitStatusChargePairVec(hitStatusChargePairVec.begin() + lowCutIdx, hitStatusChargePairVec.begin() + hiCutIdx).swap(hitStatusChargePairVec);
504 
505  // Put back in time order
506 // std::sort(hitStatusChargePairVec.begin(),hitStatusChargePairVec.end(),[](const auto& left, const auto& right){return left.first->PeakTime() < right.first->PeakTime();});
507 
508  // Tag the leading and trailing hits so as to not use them
509  std::transform(hitStatusChargePairVec.begin(),hitStatusChargePairVec.begin()+lowCutIdx,hitStatusChargePairVec.begin(), [](const auto& hitPair){return HitStatusChargePair(hitPair.first,StatusChargePair(false,hitPair.second.second));});
510  std::transform(hitStatusChargePairVec.begin()+hiCutIdx,hitStatusChargePairVec.end(),hitStatusChargePairVec.begin()+hiCutIdx,[](const auto& hitPair){return HitStatusChargePair(hitPair.first,StatusChargePair(false,hitPair.second.second));});
511 
513 
514  GetPrincipalComponents2D(hitStatusChargePairVec, pca);
515 
516  // Reject the outliers
517  RejectOutliers(hitStatusChargePairVec, pca);
518 
519  // Recompute the pca
520  GetPrincipalComponents2D(hitStatusChargePairVec, pca);
521 
522  // If the PCA faild then we should bail out
523  if (!pca.getSvdOK()) continue;
524 
525  // Now get the 3D PCA so we can use this to help select on track straightness
526  PrincipalComponents3D pca3D;
527 
528  GetPrincipalComponents3D(hitStatusChargePairVec, hitPointDirTupleMap, pca3D);
529 
530  const PrincipalComponents2D::EigenVectors& eigenVectors = pca.getEigenVectors();
531 
532  double attenuation = eigenVectors.row(1)[1] / eigenVectors.row(1)[0];
533 
534  // Want to find the wire range (or should it be the number of wires?)
535  unsigned maxWire(0);
536  unsigned minWire(100000);
537 
538  std::set<unsigned> usedWiresSet;
539 
540  for(const auto& hitPair : hitStatusChargePairVec)
541  {
542  unsigned wire = hitPair.first.first->WireID().Wire;
543 
544  usedWiresSet.insert(wire);
545 
546  if (wire > maxWire) maxWire = wire;
547  if (wire < minWire) minWire = wire;
548  }
549 
550  geo::WireID wireID = hitStatusChargePairVec.front().first.first->WireID();
551 
552  anab::TPCPurityInfo purityInfo;
553 
554  purityInfo.Run = event.run();
555  purityInfo.Subrun = event.subRun();
556  purityInfo.Event = event.event();
557  purityInfo.Cryostat = wireID.Cryostat;
558  purityInfo.TPC = wireID.TPC;
559  purityInfo.Wires = usedWiresSet.size(); //maxWire - minWire;
560  purityInfo.Ticks = hitStatusChargePairVec.back().first.first->PeakTime() - firstHitTime;
561  purityInfo.Attenuation = -attenuation;
562  purityInfo.FracError = std::sqrt(pca.getEigenValues()[0] / pca.getEigenValues()[1]);
563 
564  outputPtrVector->emplace_back(purityInfo);
565 
566  if (fDiagnosticTuple)
567  {
568  fRunNumber = event.run();
569  fSubRunNumber = event.subRun();
570  fEventNumber = event.event();
571  fCryostat = wireID.Cryostat;
572  fTPC = wireID.TPC;
573  fTrackIdx = trackIdx;
574  fWireRange = maxWire - minWire;
575  fWires = usedWiresSet.size();
576  fTicks = hitStatusChargePairVec.back().first.first->PeakTime() - firstHitTime;
577  fAttenuation = -attenuation;
578  fError = std::sqrt(pca.getEigenValues()[0] / pca.getEigenValues()[1]);
579 
580  // Test putting this back into track index order
581  std::sort(hitStatusChargePairVec.begin(),hitStatusChargePairVec.end(),[](const auto& left,const auto& right){return left.first.second->Index() < right.first.second->Index();});
582 
583  const geo::Point_t& trackStartPos = track->LocationAtPoint(hitStatusChargePairVec.front().first.second->Index());
584  const geo::Vector_t trackStartDir = track->DirectionAtPoint(hitStatusChargePairVec.front().first.second->Index());
585 
586  fTrackStartXVec.emplace_back(trackStartPos.X());
587  fTrackStartYVec.emplace_back(trackStartPos.Y());
588  fTrackStartZVec.emplace_back(trackStartPos.Z());
589  fTrackDirXVec.emplace_back(trackStartDir.X());
590  fTrackDirYVec.emplace_back(trackStartDir.Y());
591  fTrackDirZVec.emplace_back(trackStartDir.Z());
592 
593  const geo::Point_t& trackEndPos = track->LocationAtPoint(hitStatusChargePairVec.back().first.second->Index());
594  const geo::Vector_t trackEndDir = track->DirectionAtPoint(hitStatusChargePairVec.back().first.second->Index());
595 
596  fTrackEndXVec.emplace_back(trackEndPos.X());
597  fTrackEndYVec.emplace_back(trackEndPos.Y());
598  fTrackEndZVec.emplace_back(trackEndPos.Z());
599  fTrackEndDirXVec.emplace_back(trackEndDir.X());
600  fTrackEndDirYVec.emplace_back(trackEndDir.Y());
601  fTrackEndDirZVec.emplace_back(trackEndDir.Z());
602 
603  // 2D PCA of time vs charge
604  for(size_t rowIdx = 0; rowIdx < 2; rowIdx++)
605  {
606  for(size_t colIdx = 0; colIdx < 2; colIdx++) fPCAAxes2D.emplace_back(eigenVectors.row(rowIdx)[colIdx]);
607  }
608 
609  fEigenValues2D.emplace_back(pca.getEigenValues()[0]);
610  fEigenValues2D.emplace_back(pca.getEigenValues()[1]);
611 
612  fMeanPosition2D.emplace_back(pca.getAvePosition()[0]);
613  fMeanPosition2D.emplace_back(pca.getAvePosition()[1]);
614 
615  // 3D PCA of track trajectory points
616  const PrincipalComponents3D::EigenVectors& eigenVectors3D = pca3D.getEigenVectors();
617 
618  for(size_t rowIdx = 0; rowIdx < 3; rowIdx++)
619  {
620  for(size_t colIdx = 0; colIdx < 3; colIdx++) fPCAAxes3D.emplace_back(eigenVectors3D.row(rowIdx)[colIdx]);
621  }
622 
623  fEigenValues3D.emplace_back(pca3D.getEigenValues()[0]);
624  fEigenValues3D.emplace_back(pca3D.getEigenValues()[1]);
625  fEigenValues3D.emplace_back(pca3D.getEigenValues()[2]);
626 
627  fMeanPosition3D.emplace_back(pca3D.getAvePosition()[0]);
628  fMeanPosition3D.emplace_back(pca3D.getAvePosition()[1]);
629  fMeanPosition3D.emplace_back(pca3D.getAvePosition()[2]);
630 
631  for(const auto& hitPair : hitStatusChargePairVec)
632  {
633  fTickVec.emplace_back(hitPair.first.first->PeakTime());
634  fChargeVec.emplace_back(hitPair.second.second);
635  fDeltaXVec.emplace_back(hitPair.first.second->Dx());
636  fGoodnessOfFitVec.emplace_back(hitPair.first.first->GoodnessOfFit());
637  fDegreesOfFreeVec.emplace_back(hitPair.first.first->DegreesOfFreedom());
638  fSnippetLengthVec.emplace_back(hitPair.first.first->EndTick() - hitPair.first.first->StartTick());
639  fGoodHitVec.emplace_back(hitPair.second.first);
640 
641  // Want the cos(theta_yz) for this hit
642  const geo::Vector_t& hitDir = std::get<1>(hitPointDirTupleMap[hitPair.first.first.get()]);
643  const geo::Vector_t& wireDir = std::get<2>(hitPointDirTupleMap[hitPair.first.first.get()]);
644 
645  // Wire will already be in the YZ plane, but need to project hitDir to that plane
646  geo::Vector_t hitDirYZ(0.,hitDir.Y(),hitDir.Z());
647 
648  hitDirYZ /= std::sqrt(hitDirYZ.Mag2());
649 
650  fCosThetaYZ.emplace_back(hitDirYZ.Dot(wireDir));
651  }
652 
653  fDiagnosticTree->Fill();
654 
655  fTrackStartXVec.clear();
656  fTrackStartYVec.clear();
657  fTrackStartZVec.clear();
658  fTrackDirXVec.clear();
659  fTrackDirYVec.clear();
660  fTrackDirZVec.clear();
661  fTrackEndXVec.clear();
662  fTrackEndYVec.clear();
663  fTrackEndZVec.clear();
664  fTrackEndDirXVec.clear();
665  fTrackEndDirYVec.clear();
666  fTrackEndDirZVec.clear();
667  fPCAAxes2D.clear();
668  fEigenValues2D.clear();
669  fMeanPosition2D.clear();
670  fPCAAxes3D.clear();
671  fEigenValues3D.clear();
672  fMeanPosition3D.clear();
673  fTickVec.clear();
674  fChargeVec.clear();
675  fDeltaXVec.clear();
676  fGoodnessOfFitVec.clear();
677  fDegreesOfFreeVec.clear();
678  fSnippetLengthVec.clear();
679  fGoodHitVec.clear();
680  fCosThetaYZ.clear();
681  }
682  }
683  }
684 
685  //put info onto the event
686  event.put(std::move(outputPtrVector));
687 
688  return;
689 }
690 
691 void TPCPurityMonitor::endJob()
692 {
693  return;
694 }
695 
696 // Length of reconstructed track.
697 //----------------------------------------------------------------------------
698 double TPCPurityMonitor::length(const recob::Track* track)
699 {
700  double result(0.);
701 /*
702  TVector3 disp(track->LocationAtPoint(0));
703  TVector3 lastPoint(track->LocationAtPoint(0));
704  TVector3 lastDir(0.,0.,0.);
705  int n(track->NumberTrajectoryPoints());
706 
707  for(int i = 1; i < n; ++i)
708  {
709  const TVector3& pos = track->LocationAtPoint(i);
710 
711  TVector3 trajDir = pos - lastPoint;
712 
713  if (trajDir.Mag2()) trajDir.SetMag(1.);
714 
715 // if (lastDir.Dot(trajDir) >= 0.)
716 // {
717  disp -= pos;
718  result += disp.Mag();
719  disp = pos;
720 // }
721 
722  lastPoint = pos;
723  lastDir = trajDir;
724  }
725 */
726  return result;
727 }
728 
729 // Length of reconstructed track.
730 //----------------------------------------------------------------------------
731 double TPCPurityMonitor::projectedLength(const recob::Track* track)
732 {
733  double result(0.);
734 /*
735  TVector3 lastPoint(track->LocationAtPoint(0));
736  TVector3 lastDir(track->DirectionAtPoint(0));
737  int n(track->NumberTrajectoryPoints());
738 
739  for(int i = 1; i < n; ++i)
740  {
741  const TVector3& newPoint = track->LocationAtPoint(i);
742 
743  TVector3 lastToNewPoint = newPoint - lastPoint;
744  double arcLenToDoca = lastDir.Dot(lastToNewPoint);
745 
746  result += arcLenToDoca;
747  lastPoint = lastPoint + arcLenToDoca * lastDir;
748  lastDir = track->DirectionAtPoint(i);
749  }
750 */
751  return result;
752 }
753 
754 
755 void TPCPurityMonitor::GetPrincipalComponents2D(const HitStatusChargePairVec& hitPairVector, PrincipalComponents2D& pca) const
756 {
757  // Run through the HitPairList and get the mean position of all the hits
758  Eigen::Vector2d meanPos(Eigen::Vector2d::Zero());
759  double meanWeightSum(0.);
760  int numPairsInt(0);
761 
762  float startTime = 0.; //hitPairVector.front().first->PeakTime();
763 
764  for (const auto& hitPair : hitPairVector)
765  {
766  if (!hitPair.second.first) continue;
767 
768  const recob::Hit* hit = hitPair.first.first.get();
769 
770  // Weight the hit by the peak time difference significance
771  double weight = fWeightByChiSq ? 1./hit->GoodnessOfFit() : 1.;
772 
773  meanPos(0) += fSamplingRate * (hit->PeakTime() - startTime) * weight;
774  meanPos(1) += std::log(hitPair.second.second) * weight;
775  numPairsInt++;
776 
777  meanWeightSum += weight;
778  }
779 
780  meanPos /= meanWeightSum;
781 
782  // Define elements of our covariance matrix
783  double xi2(0.);
784  double xiyi(0.);
785  double yi2(0.0);
786  double weightSum(0.);
787 
788  // Back through the hits to build the matrix
789  for (const auto& hitPair : hitPairVector)
790  {
791  if (!hitPair.second.first) continue;
792 
793  const recob::Hit* hit = hitPair.first.first.get();
794 
795  double weight = fWeightByChiSq ? 1./hit->GoodnessOfFit() : 1.;
796 
797  double x = (fSamplingRate * (hit->PeakTime() - startTime) - meanPos(0)) * weight;
798  double y = (std::log(hitPair.second.second) - meanPos(1)) * weight;
799 
800  weightSum += weight * weight;
801 
802  xi2 += x * x;
803  xiyi += x * y;
804  yi2 += y * y;
805  }
806 
807  // Using Eigen package
808  Eigen::Matrix2d sig;
809 
810  sig << xi2, xiyi, xiyi, yi2;
811 
812  sig *= 1. / weightSum;
813 
814  Eigen::SelfAdjointEigenSolver<Eigen::Matrix2d> eigenMat(sig);
815 
816  if (eigenMat.info() == Eigen::ComputationInfo::Success)
817  {
818  // Now copy outputPrincipalCo
819  // The returned eigen values and vectors will be returned in an xyz system where x is the smallest spread,
820  // y is the next smallest and z is the largest. Adopt that convention going forward
821  PrincipalComponents2D::EigenValues eigenVals = eigenMat.eigenvalues();
822  PrincipalComponents2D::EigenVectors eigenVecs = eigenMat.eigenvectors().transpose();
823 
824  // Store away
825  // NOTE: the major axis will be the second entry, the minor axis will be the first
826  pca = PrincipalComponents2D(true, numPairsInt, eigenVals, eigenVecs, meanPos);
827  }
828  else
829  {
830  mf::LogDebug("Cluster3D") << "PCA decompose failure, numPairs = " << numPairsInt << std::endl;
831  pca = PrincipalComponents2D();
832  }
833 
834  return;
835 }
836 
837 void TPCPurityMonitor::GetPrincipalComponents3D(const HitStatusChargePairVec& hitPairVector, HitPointDirTupleMap& hitPointDirTupleMap, PrincipalComponents3D& pca) const
838 {
839  // Run through the HitPairList and get the mean position of all the hits
840  Eigen::Vector3d meanPos(Eigen::Vector3d::Zero());
841  double meanWeightSum(0.);
842  int numPairsInt(0);
843 
844  for (const auto& hitPair : hitPairVector)
845  {
846  if (!hitPair.second.first) continue;
847 
848  const recob::Hit* hit = hitPair.first.first.get();
849 
850  geo::Point_t hitPos = std::get<0>(hitPointDirTupleMap[hit]);
851 
852  // Weight the hit by the peak time difference significance
853  double weight = fWeightByChiSq ? 1./hit->GoodnessOfFit() : 1.;
854 
855  meanPos += Eigen::Vector3d(hitPos.X(),hitPos.Y(),hitPos.Z());
856 
857  numPairsInt++;
858 
859  meanWeightSum += weight;
860  }
861 
862  meanPos /= meanWeightSum;
863 
864  // Define elements of our covariance matrix
865  double xi2(0.);
866  double xiyi(0.);
867  double xizi(0.);
868  double yi2(0.);
869  double yizi(0.);
870  double zi2(0.);
871  double weightSum(0.);
872 
873  // Back through the hits to build the matrix
874  for (const auto& hitPair : hitPairVector)
875  {
876  if (!hitPair.second.first) continue;
877 
878  const recob::Hit* hit = hitPair.first.first.get();
879 
880  double weight = fWeightByChiSq ? 1./hit->GoodnessOfFit() : 1.;
881 
882  geo::Point_t hitPos = std::get<0>(hitPointDirTupleMap[hit]);
883  Eigen::Vector3d weightedHitPos = Eigen::Vector3d(hitPos.X(),hitPos.Y(),hitPos.Z()) - meanPos;
884 
885  weightSum += weight * weight;
886 
887  xi2 += weightedHitPos[0] * weightedHitPos[0];
888  xiyi += weightedHitPos[0] * weightedHitPos[1];
889  xizi += weightedHitPos[0] * weightedHitPos[2];
890  yi2 += weightedHitPos[1] * weightedHitPos[1];
891  yizi += weightedHitPos[1] * weightedHitPos[2];
892  zi2 += weightedHitPos[2] * weightedHitPos[2];
893  }
894 
895  // Using Eigen package
896  Eigen::Matrix3d sig;
897 
898  sig << xi2, xiyi, xizi, xiyi, yi2, yizi, xizi, yizi, zi2;
899 
900  sig *= 1. / weightSum;
901 
902  Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> eigenMat(sig);
903 
904  if (eigenMat.info() == Eigen::ComputationInfo::Success)
905  {
906  // Now copy outputPrincipalCo
907  // The returned eigen values and vectors will be returned in an xyz system where x is the smallest spread,
908  // y is the next smallest and z is the largest. Adopt that convention going forward
909  PrincipalComponents3D::EigenValues eigenVals = eigenMat.eigenvalues();
910  PrincipalComponents3D::EigenVectors eigenVecs = eigenMat.eigenvectors().transpose();
911 
912  // Store away
913  // NOTE: the major axis will be the second entry, the minor axis will be the first
914  pca = PrincipalComponents3D(true, numPairsInt, eigenVals, eigenVecs, meanPos);
915  }
916  else
917  {
918  mf::LogDebug("Cluster3D") << "PCA decompose failure, numPairs = " << numPairsInt << std::endl;
919  pca = PrincipalComponents3D();
920  }
921 
922  return;
923 }
924 
925 void TPCPurityMonitor::RejectOutliers(HitStatusChargePairVec& hitPairVector, const PrincipalComponents2D& pca) const
926 {
927  double slope = pca.getEigenVectors().row(1)[1] / pca.getEigenVectors().row(1)[0];
928  const Eigen::Vector2d& avePos = pca.getAvePosition();
929 
930  using HitPairDeltaLogChargePair = std::pair<HitStatusChargePair*,double>;
931  using HitPairDeltaLogChargePairVec = std::vector<HitPairDeltaLogChargePair>;
932 
933  HitPairDeltaLogChargePairVec hitPairDeltaLogChargePairVec;
934 
935  for(auto& hitPair : hitPairVector)
936  {
937  // We are only interested in the "good" hits here
938  if (hitPair.second.first)
939  {
940  double predLogCharge = (fSamplingRate * hitPair.first.first->PeakTime() - avePos[0]) * slope + avePos[1];
941  double deltaLogCharge = std::log(hitPair.second.second) - predLogCharge;
942 
943  hitPairDeltaLogChargePairVec.emplace_back(&hitPair,deltaLogCharge);
944  }
945  }
946 
947  // Sort hits by their deviation from the prediction
948  std::sort(hitPairDeltaLogChargePairVec.begin(),hitPairDeltaLogChargePairVec.end(),[](const auto& left, const auto& right){return left.second < right.second;});
949 
950  // Go through and tag those we are rejecting
951  size_t loRejectIdx = 0.01 * hitPairDeltaLogChargePairVec.size();
952  size_t hiRejectIdx = fOutlierRejectFrac * hitPairDeltaLogChargePairVec.size();
953 
954  const double outlierReject = 0.75;
955 
956  for(size_t idx = 0; idx < hitPairDeltaLogChargePairVec.size(); idx++)
957  {
958  if (idx < loRejectIdx || idx > hiRejectIdx) hitPairDeltaLogChargePairVec[idx].first->second.first = false;
959  if (hitPairDeltaLogChargePairVec[idx].second < -outlierReject) hitPairDeltaLogChargePairVec[idx].first->second.first = false;
960  }
961 
962  return;
963 }
964 
965 
966 } // namespace TPCPurityMonitor
967 
968 #endif // TPCPurityMonitor_module
float fOutlierRejectFrac
Fraction of outliers to reject.
Geometry description of a TPC wireThe wire is a single straight segment on a wire plane...
Definition: WireGeo.h:65
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space.
Definition: geo_vectors.h:164
std::vector< art::InputTag > fTrackLabelVec
labels for source of tracks
EigenValues fEigenValues
Eigen values from SVD decomposition.
int fWireRange
Last - first wire number.
bool fWeightByChiSq
Weight the PCA by the hit chisquare.
std::vector< double > fPCAAxes2D
Axes for PCA.
double length(const recob::Track *track)
Utilities related to art service access.
TTree * fDiagnosticTree
Pointer to our tree.
static constexpr Sample_t transform(Sample_t sample)
std::vector< double > fTrackEndDirYVec
Ending x direction of track.
process_name opflash particleana ie x
std::vector< double > fTrackDirZVec
Starting x direction of track.
std::vector< double > fMeanPosition3D
Mean position used for PCA.
unsigned fMinNumHits
Minimum number of hits.
Declaration of signal hit object.
walls no right
Definition: selectors.fcl:105
int fEventNumber
event number this event
std::vector< bool > fGoodHitVec
Hits were considered good.
pdgs p
Definition: selectors.fcl:22
PrincipalComponents2D(bool ok, int nHits, const EigenValues &eigenValues, const EigenVectors &eigenVecs, const Eigen::Vector2d &avePos)
std::vector< double > fGoodnessOfFitVec
Goodness of the hit&#39;s fit.
Class to keep data related to recob::Hit associated with recob::Track.
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:212
std::unordered_map< const recob::Hit *, PointDirTuple > HitPointDirTupleMap
std::vector< double > fEigenValues2D
Eigen values.
for pfile in ack l reconfigure(.*) override"` do echo "checking $
process_name use argoneut_mc_hitfinder track
TPCPurityMonitor(fhicl::ParameterSet const &pset)
Data related to recob::Hit associated with recob::Track.The purpose is to collect several variables t...
Definition: TrackHitMeta.h:43
void reconfigure(fhicl::ParameterSet const &pset)
process_name hit
Definition: cheaterreco.fcl:51
std::tuple< geo::Point_t, geo::Vector_t, geo::Vector_t > PointDirTuple
float GoodnessOfFit() const
Degrees of freedom in the determination of the hit signal shape (-1 by default)
Definition: Hit.h:228
std::pair< art::Ptr< recob::Hit >, const recob::TrackHitMeta * > HitMetaPair
std::vector< double > fTickVec
vector of ticks
double fAttenuation
Attenuation from calc.
std::pair< HitMetaPair, StatusChargePair > HitStatusChargePair
unsigned int Subrun
std::vector< double > fTrackDirXVec
Starting x direction of track.
void RejectOutliers(HitStatusChargePairVec &hitPairVector, const PrincipalComponents2D &pca) const
T abs(T value)
void GetPrincipalComponents2D(const HitStatusChargePairVec &hitPairVector, PrincipalComponents2D &pca) const
std::vector< double > fEigenValues3D
Eigen values 3D.
std::vector< double > fTrackEndXVec
Ending x position of track.
unsigned int Event
std::vector< double > fTrackEndDirZVec
Ending x direction of track.
process_name opflash particleana ie ie y
std::vector< double > fPCAAxes3D
Axes for PCA 3D.
std::vector< double > fDeltaXVec
Keep track of hits path length from track fit.
Eigen::Vector3d fAvePosition
Average position of hits fed to PCA.
std::vector< double > fChargeVec
vector of hit charges
Collect all the RawData header files together.
unsigned int Cryostat
std::vector< int > fSnippetLengthVec
Lenght from start/end of hit.
std::vector< double > fTrackEndZVec
Ending z position of track.
walls no left
Definition: selectors.fcl:105
Description of geometry of one entire detector.
Declaration of cluster object.
EigenValues fEigenValues
Eigen values from SVD decomposition.
Definition of data types for geometry description.
Provides recob::Track data product.
Vector Direction() const
Definition: WireGeo.h:587
bool fUseHitIntegral
Setting to false swaps to &quot;SummedADC&quot;.
std::vector< double > fTrackDirYVec
Starting x direction of track.
PrincipalComponents3D(bool ok, int nHits, const EigenValues &eigenValues, const EigenVectors &eigenVecs, const Eigen::Vector3d &avePos)
WireGeo const & Wire(geo::WireID const &wireid) const
Returns the specified wire.
std::vector< double > fTrackEndDirXVec
Ending x direction of track.
float PeakTime() const
Time of the signal peak, in tick units.
Definition: Hit.h:218
Eigen::Vector2d fAvePosition
Average position of hits fed to PCA.
std::vector< double > fCosThetaYZ
cos(thetaYZ) hit trajector to wire
void GetPrincipalComponents3D(const HitStatusChargePairVec &hitPairVector, HitPointDirTupleMap &, PrincipalComponents3D &pca) const
bool fDiagnosticTuple
Output the diagnostic tuple.
int fSubRunNumber
sub run number this event
float fMinRejectFraction
Reject this fraction of &quot;low Q&quot; hits.
int fCryostat
Cryostat for given track.
unsigned fSelectedPlane
Select hits from this plane.
constexpr WireID()=default
Default constructor: an invalid TPC ID.
std::vector< HitStatusChargePair > HitStatusChargePairVec
std::vector< double > fTrackStartZVec
Starting z position of track.
2D representation of charge deposited in the TDC/wire plane
Definition: Hit.h:48
art::ServiceHandle< art::TFileService > tfs
std::vector< double > fTrackStartYVec
Starting y position of track.
TCEvent evt
Definition: DataStructs.cxx:8
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:406
std::vector< double > fTrackStartXVec
Starting x position of track.
double sampling_rate(DetectorClocksData const &data)
Returns the period of the TPC readout electronics clock.
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:184
float fMinTickRange
Require track to span some number of ticks.
float fMaxRejectFraction
Reject this fraction of &quot;high Q&quot; hits.
std::vector< int > fDegreesOfFreeVec
Degrees of freedom.
double projectedLength(const recob::Track *track)
std::vector< double > fMeanPosition2D
Mean position used for PCA.
art framework interface to geometry description
BEGIN_PROLOG could also be cout
std::vector< double > fTrackEndYVec
Ending y position of track.
Track from a non-cascading particle.A recob::Track consists of a recob::TrackTrajectory, plus additional members relevant for a &quot;fitted&quot; track:
float fAssumedELifetime
Lifetime assumed for calculation.
float fSamplingRate
Recover the sampling rate from the clock data.