PhotonCounterT0Matching_module.cc
Go to the documentation of this file.
1 /////////////////////////////////////////////////////////////////////////////
2 /// Class: PhotonCounterT0Matching
3 /// Module Type: producer
4 /// File: PhotonCounterT0Matching_module.cc
5 ///
6 /// Author: Thomas Karl Warburton
7 /// E-mail address: k.warburton@sheffield.ac.uk
8 ///
9 /// Generated at Wed Mar 25 13:54:28 2015 by Thomas Warburton using artmod
10 /// from cetpkgsupport v1_08_04.
11 ///
12 /// This module tries to match a reconstructed track with a reconstructed
13 /// flash with the purpose of making an anab::T0 data product.
14 /// It does this by looping through the reconstructed tracks and for each
15 /// track seeing if any of the reconstructed flashes could be associated with
16 /// it (if it is within 1 drift window). If a flash can be matched with the
17 /// track then some matching criteria are calculated;
18 /// A PE vs X relationship
19 /// The separation of the flash centre to a track space point in YZ
20 /// The flash which has the smallest summed square of these quantities is then
21 /// attributed to this track.
22 /// It is possible for a flash to be attributed to multiple tracks, but only
23 /// one flash is attributed to each track.
24 /// If there are no flashes within one drift window of the track, then no flash
25 /// is assigned. Therefore it is important to look at other methods of using
26 /// other T0 finders in addition to this one.
27 ///
28 /// The module takes a reconstructed track as input.
29 /// The module outputs an anab::T0 object
30 /////////////////////////////////////////////////////////////////////////////
31 
32 // Framework includes
37 #include "art_root_io/TFileService.h"
38 #include "canvas/Persistency/Common/FindManyP.h"
40 #include "fhiclcpp/ParameterSet.h"
41 
42 #include <iostream>
43 #include <memory>
44 
45 // LArSoft
55 
56 // ROOT
57 #include "TH1D.h"
58 #include "TH2D.h"
59 #include "TTree.h"
60 
61 namespace lbne {
62  class PhotonCounterT0Matching;
63 }
64 
66 public:
68  // The destructor generated by the compiler is fine for classes
69  // without bare pointers or other resource use.
70 
71  // Plugins should not be copied or assigned.
76 
77  // Required functions.
78  void produce(art::Event& e) override;
79 
80  // Selected optional functions.
81  void beginJob() override;
82 
83 private:
84  // Internal functions.....
85  void TrackProp(double TrackStart_X,
86  double TrackEnd_X,
87  double& TrackLength_X,
88  double& TrackCentre_X,
89  double TrackStart_Y,
90  double TrackEnd_Y,
91  double& TrackLength_Y,
92  double& TrackCentre_Y,
93  double TrackStart_Z,
94  double TrackEnd_Z,
95  double& TrackLength_Z,
96  double& TrackCentre_Z,
97  double trkTimeStart,
98  double trkTimeEnd,
99  double& trkTimeLengh,
100  double& trkTimeCentre,
101  double& TrackLength);
102  double DistFromPoint(double StartY,
103  double EndY,
104  double StartZ,
105  double EndZ,
106  double PointY,
107  double PointZ);
108 
109  // Params got from fcl file.......
116  double fPredictedXPower = 1;
122  double fPEThreshold;
124 
125  // Variables used in module.......
127  double TrackLength_Y, TrackCentre_Y /* , BestTrackCentre_Y */;
128  double TrackLength_Z, TrackCentre_Z /* , BestTrackCentre_Z */;
130 
142 
143  double YZSep, MCTruthT0;
144  // Histograms in TFS branches
145  TTree* fTree;
146  TH2D* hPredX_T;
147  TH2D* hPredX_PE;
148  TH2D* hPredX_T_PE;
155 };
156 
158 {
159  // Call appropriate produces<>() functions here.
160  produces<std::vector<anab::T0>>();
161  produces<art::Assns<recob::Track, anab::T0>>();
162  produces<art::Assns<recob::Shower, anab::T0>>();
163 
164  fTrackModuleLabel = (p.get<std::string>("TrackModuleLabel"));
165  fShowerModuleLabel = (p.get<std::string>("ShowerModuleLabel"));
166  fHitsModuleLabel = (p.get<std::string>("HitsModuleLabel"));
167  fFlashModuleLabel = (p.get<std::string>("FlashModuleLabel"));
168  fTruthT0ModuleLabel = (p.get<std::string>("TruthT0ModuleLabel"));
169 
170  fPredictedXConstant = (p.get<double>("PredictedXConstant"));
171  fPredictedExpConstant = (p.get<double>("PredictedExpConstant"));
172  fPredictedExpGradient = (p.get<double>("PredictedExpGradient"));
173 
174  fDriftWindowSize = (p.get<double>("DriftWindowSize"));
175  fWeightOfDeltaYZ = (p.get<double>("WeightOfDeltaYZ"));
176  fMatchCriteria = (p.get<double>("MatchCriteria"));
177  fPEThreshold = (p.get<double>("PEThreshold"));
178 
179  fVerbosity = (p.get<bool>("Verbose", false));
180 }
181 
182 void
184 {
185  // Implementation of optional member function here.
187  fTree = tfs->make<TTree>("PhotonCounterT0Matching", "PhotonCounterT0");
188  fTree->Branch("TrackCentre_X", &BestTrackCentre_X, "TrackCentre_X/D");
189  fTree->Branch("PredictedX", &BestPredictedX, "PredictedX/D");
190  fTree->Branch("TrackTimeCent", &BesttrkTimeCentre, "TimeSepPredX/D");
191  fTree->Branch("FlashTime", &BestFlashTime, "FlashTime/D");
192  fTree->Branch("TimeSep", &BestTimeSep, "TimeSep/D");
193  fTree->Branch("TimeSepPredX", &BestTimeSepPredX, "TimeSepPredX/D");
194  fTree->Branch("minYZSep", &BestminYZSep, "minYZSep/D");
195  fTree->Branch("FitParam", &BestFitParam, "FitParam/D");
196  fTree->Branch("MCTruthT0", &MCTruthT0, "MCTruthT0/D");
197 
198  hPredX_T = tfs->make<TH2D>("hPredX_T",
199  "Predicted X from timing information against reconstructed X; "
200  "Reconstructed X (cm); Predicted X (cm)",
201  30,
202  0,
203  300,
204  30,
205  0,
206  300);
207  hPredX_PE = tfs->make<TH2D>("hPredX_PE",
208  "Predicted X from PE information against reconstructed X; "
209  "Reconstructed X (cm); Predicted X (cm)",
210  30,
211  0,
212  300,
213  30,
214  0,
215  300);
216  hPredX_T_PE = tfs->make<TH2D>("hPredX_T_PE",
217  "Predicted X position from time and PE information; Predicted X "
218  "from timing information (cm); Predicted X from PE information",
219  60,
220  0,
221  300,
222  60,
223  0,
224  300);
225  hdeltaX_deltaYZ = tfs->make<TH2D>(
226  "hdeltaX_deltaYZ",
227  "Difference between X predicted from PE's and T agaisnt distance of flash from track in YZ; "
228  "Difference in X predicted from PE's and T (cm); Distance of flash from track in YZ (cm)",
229  40,
230  0,
231  200,
232  40,
233  0,
234  100);
235  hdeltaYZ_Length = tfs->make<TH2D>("hdeltaYZ_Length",
236  "Distance of flash from track against track length; Distance "
237  "from flash to track (cm); Track length (cm)",
238  20,
239  0,
240  100,
241  60,
242  0,
243  300);
245  tfs->make<TH2D>("hFitParam_Length",
246  "How fit correlates with track length; Fit correlation; Track Length (cm)",
247  50,
248  0,
249  250,
250  30,
251  0,
252  300);
253  hPhotonT0_MCT0 = tfs->make<TH2D>("hPhotonT0_MCT0",
254  "Comparing Photon Counter reconstructed T0 against MCTruth T0; "
255  "Photon Counter T0 (us); MCTruthT0 T0 (us)",
256  1760,
257  -1600,
258  16000,
259  1760,
260  -1600,
261  16000);
262  hT0_diff_full = tfs->make<TH1D>(
263  "hT0_diff_full",
264  "Difference between MCTruth T0 and photon detector T0; Time difference (us); Number",
265  500,
266  -2500,
267  2500);
268  hT0_diff_zoom = tfs->make<TH1D>(
269  "hT0_diff_zoom",
270  "Difference between MCTruth T0 and photon detector T0; Time difference (us); Number",
271  320,
272  -1.6,
273  1.6);
274 }
275 
276 void
278 {
279  // Access art services...
281  auto const clock_data =
283  auto const detprop =
285 
286  //TrackList handle
287  art::Handle<std::vector<recob::Track>> trackListHandle;
288  std::vector<art::Ptr<recob::Track>> tracklist;
289  if (evt.getByLabel(fTrackModuleLabel, trackListHandle))
290  art::fill_ptr_vector(tracklist, trackListHandle);
291 
292  //ShowerList handle
293  art::Handle<std::vector<recob::Shower>> showerListHandle;
294  std::vector<art::Ptr<recob::Shower>> showerlist;
295  if (evt.getByLabel(fShowerModuleLabel, showerListHandle))
296  art::fill_ptr_vector(showerlist, showerListHandle);
297 
298  //HitList Handle
300  std::vector<art::Ptr<recob::Hit>> hitlist;
301  if (evt.getByLabel(fHitsModuleLabel, hitListHandle)) art::fill_ptr_vector(hitlist, hitListHandle);
302 
303  //FlashList Handle
305  std::vector<art::Ptr<recob::OpFlash>> flashlist;
306  if (evt.getByLabel(fFlashModuleLabel, flashListHandle))
307  art::fill_ptr_vector(flashlist, flashListHandle);
308 
309  // Create anab::T0 objects and make association with recob::Track
310 
311  std::unique_ptr<std::vector<anab::T0>> T0col(new std::vector<anab::T0>);
312  std::unique_ptr<art::Assns<recob::Track, anab::T0>> Trackassn(
314  std::unique_ptr<art::Assns<recob::Shower, anab::T0>> Showerassn(
316 
317  if (trackListHandle.isValid() && flashListHandle.isValid()) {
318  //Access tracks and hits
319  art::FindManyP<recob::Hit> fmtht(trackListHandle, evt, fTrackModuleLabel);
320  art::FindMany<anab::T0> fmtruth(trackListHandle, evt, fTruthT0ModuleLabel);
321 
322  size_t NTracks = tracklist.size();
323  size_t NFlashes = flashlist.size();
324 
325  if (fVerbosity)
326  std::cout << "There were " << NTracks << " tracks and " << NFlashes
327  << " flashes in this event." << std::endl;
328 
329  // Now to access PhotonCounter for each track...
330  for (size_t iTrk = 0; iTrk < NTracks; ++iTrk) {
331  if (fVerbosity) std::cout << "\n New Track " << (int)iTrk << std::endl;
332  // Reset Variables.
335  bool ValidTrack = false;
336 
337  // Work out Properties of the track.
338  recob::Track::Point_t trackStart, trackEnd;
339  std::tie(trackStart, trackEnd) = tracklist[iTrk]->Extent();
340  std::vector<art::Ptr<recob::Hit>> allHits = fmtht.at(iTrk);
341  size_t nHits = allHits.size();
342  trkTimeStart = allHits[nHits - 1]->PeakTime() /
343  clock_data.TPCClock().Frequency(); // Got in ticks, now in us!
344  trkTimeEnd =
345  allHits[0]->PeakTime() / clock_data.TPCClock().Frequency(); // Got in ticks, now in us!
346  TrackProp(trackStart.X(),
347  trackEnd.X(),
350  trackStart.Y(),
351  trackEnd.Y(),
354  trackStart.Z(),
355  trackEnd.Z(),
358  trkTimeStart,
359  trkTimeEnd,
360  trkTimeLengh,
361  trkTimeCentre, // times in us!
362  TrackLength);
363 
364  // Some cout statement about track properties.
365  if (fVerbosity) {
366  std::cout << trackStart.X() << " " << trackEnd.X() << " " << TrackLength_X << " "
367  << TrackCentre_X << "\n"
368  << trackStart.Y() << " " << trackEnd.Y() << " " << TrackLength_Y << " "
369  << TrackCentre_Y << "\n"
370  << trackStart.Z() << " " << trackEnd.Z() << " " << TrackLength_Z << " "
371  << TrackCentre_Z << "\n"
372  << trkTimeStart << " " << trkTimeEnd << " " << trkTimeLengh << " "
373  << trkTimeCentre << std::endl;
374  }
375  // ----- Loop over flashes ------
376  for (size_t iFlash = 0; iFlash < NFlashes; ++iFlash) {
377  //Reset some flash specific quantities
378  YZSep = minYZSep = 9999;
379  FlashTime = TimeSep = 9999;
381  // Check flash could be caused by track...
382  FlashTime = flashlist[iFlash]->Time(); // Got in us!
383  TimeSep = trkTimeCentre - FlashTime; // Time in us!
384  if (TimeSep < 0 || TimeSep > (fDriftWindowSize / clock_data.TPCClock().Frequency()))
385  continue; // Times compared in us!
386 
387  // Check flash has enough PE's to satisfy our threshold
388  if (flashlist[iFlash]->TotalPE() < fPEThreshold) continue;
389 
390  // Work out some quantities for this flash...
391  // PredictedX = ( A / x^n ) + exp ( B + Cx )
392  PredictedX =
393  (fPredictedXConstant / pow(flashlist[iFlash]->TotalPE(), fPredictedXPower)) +
394  (exp(fPredictedExpConstant + (fPredictedExpGradient * flashlist[iFlash]->TotalPE())));
395  TimeSepPredX = TimeSep * detprop.DriftVelocity(); // us * cm/us = cm!
397  // Dependant on each point...
398  for (size_t Point = 1; Point < tracklist[iTrk]->NumberTrajectoryPoints(); ++Point) {
399  auto NewPoint = tracklist[iTrk]->LocationAtPoint(Point);
400  auto PrevPoint = tracklist[iTrk]->LocationAtPoint(Point - 1);
401  YZSep = DistFromPoint(NewPoint.Y(),
402  PrevPoint.Y(),
403  NewPoint.Z(),
404  PrevPoint.Z(),
405  flashlist[iFlash]->YCenter(),
406  flashlist[iFlash]->ZCenter());
407  if (Point == 1) minYZSep = YZSep;
408  if (YZSep < minYZSep) minYZSep = YZSep;
409  }
410 
411  // Determine how well matched this track is......
412  if (fMatchCriteria == 0)
413  FitParam =
415  else if (fMatchCriteria == 1)
416  FitParam = minYZSep;
417  else if (fMatchCriteria == 2)
419 
420  //----FLASH INFO-----
421  if (fVerbosity) {
422  std::cout << "\nFlash " << (int)iFlash << " " << TrackCentre_X << ", " << TimeSepPredX
423  << " - " << PredictedX << " = " << DeltaPredX << ", " << minYZSep << " -> "
424  << FitParam << std::endl;
425  }
426  //----Select best flash------
427  if (FitParam < BestFitParam) {
428  ValidTrack = true;
429  BestFlash = (int)iFlash;
438  BestFlashTime = FlashTime;
440  } // Find best Flash
441  } // Loop over Flashes
442 
443  // ---- Now Make association and fill TTree/Histos with the best matched flash.....
444  if (ValidTrack) {
445 
446  // -- Fill Histos --
453  // ------ Compare Photon Matched to MCTruth Matched -------
454  if (fmtruth.isValid()) {
455  std::vector<const anab::T0*> T0s = fmtruth.at((int)iTrk);
456  for (size_t i = 0; i < T0s.size(); ++i) {
457  MCTruthT0 = T0s[i]->Time() / 1e3; // Got in ns, now in us!!
458  hPhotonT0_MCT0->Fill(BestFlashTime, MCTruthT0);
459  hT0_diff_full->Fill(MCTruthT0 - BestFlashTime);
460  hT0_diff_zoom->Fill(MCTruthT0 - BestFlashTime);
461  }
462  }
463  // -- Fill TTree --
464  fTree->Fill();
465  //Make Association
466  T0col->push_back(anab::T0(
467  BestFlashTime * 1e3, FlashTriggerType, (int)BestFlash, (*T0col).size(), BestFitParam));
468  util::CreateAssn(*this, evt, *T0col, tracklist[iTrk], *Trackassn);
469  } // Valid Track
470  } // Loop over tracks
471  }
472  evt.put(std::move(T0col));
473  evt.put(std::move(Trackassn));
474  evt.put(std::move(Showerassn));
475 
476 } // Produce
477 // ----------------------------------------------------------------------------------------------------------------------------
478 void
480  double TrackEnd_X,
481  double& TrackLength_X,
482  double& TrackCentre_X,
483  double TrackStart_Y,
484  double TrackEnd_Y,
485  double& TrackLength_Y,
486  double& TrackCentre_Y,
487  double TrackStart_Z,
488  double TrackEnd_Z,
489  double& TrackLength_Z,
490  double& TrackCentre_Z,
491  double trkTimeStart,
492  double trkTimeEnd,
493  double& trkTimeLengh,
494  double& trkTimeCentre,
495  double& TrackLength)
496 {
497  ///Calculate central values for track X, Y, Z and time, as well as lengths and overall track length.
498  TrackLength_X = fabs(TrackEnd_X - TrackStart_X);
499  if (TrackStart_X < TrackEnd_X)
500  TrackCentre_X = TrackStart_X + 0.5 * TrackLength_X;
501  else
502  TrackCentre_X = TrackStart_X - 0.5 * TrackLength_X;
503 
504  TrackLength_Y = fabs(TrackEnd_Y - TrackStart_Y);
505  if (TrackStart_Y < TrackEnd_Y)
506  TrackCentre_Y = TrackStart_Y + 0.5 * TrackLength_Y;
507  else
508  TrackCentre_Y = TrackStart_Y - 0.5 * TrackLength_Y;
509 
510  TrackLength_Z = fabs(TrackEnd_Z - TrackStart_Z);
511  if (TrackStart_Z < TrackEnd_Z)
512  TrackCentre_Z = TrackStart_Z + 0.5 * TrackLength_Z;
513  else
514  TrackCentre_Z = TrackStart_Z - 0.5 * TrackLength_Z;
515 
516  trkTimeLengh = trkTimeEnd - trkTimeStart;
517  trkTimeCentre = trkTimeStart + 0.5 * trkTimeLengh;
518 
519  TrackLength = pow(pow((TrackEnd_X - TrackStart_X), 2) + pow((TrackEnd_Y - TrackStart_Y), 2) +
520  pow((TrackEnd_Z - TrackStart_Z), 2),
521  0.5);
522 
523  return;
524 }
525 // ----------------------------------------------------------------------------------------------------------------------------
526 double
528  double EndY,
529  double StartZ,
530  double EndZ,
531  double PointY,
532  double PointZ)
533 {
534  ///Calculate the distance between the centre of the flash and the centre of a line connecting two adjacent space points.
535  double Length = hypot(fabs(EndY - StartY), fabs(EndZ - StartZ));
536  double distance =
537  ((PointZ - StartZ) * (EndY - StartY) - (PointY - StartY) * (EndZ - StartZ)) / Length;
538  return fabs(distance);
539 }
540 // ----------------------------------------------------------------------------------------------------------------------------
float Length(const PFPStruct &pfp)
Definition: PFPUtils.cxx:3303
std::string string
Definition: nybbler.cc:12
EDProducer(fhicl::ParameterSet const &pset)
Definition: EDProducer.h:20
constexpr T pow(T x)
Definition: pow.h:72
Definition: T0.h:16
double DistFromPoint(double StartY, double EndY, double StartZ, double EndZ, double PointY, double PointZ)
art framework interface to geometry description
std::enable_if_t< std::is_arithmetic_v< T >, T > hypot(T x, T y)
Definition: hypot.h:60
bool isValid() const noexcept
Definition: Handle.h:191
bool getByLabel(std::string const &label, std::string const &instance, Handle< PROD > &result) const
Definition: DataViewImpl.h:633
const double e
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:67
std::tuple< double, double, const reco::ClusterHit3D * > Point
Definitions used by the VoronoiDiagram algorithm.
Definition: DCEL.h:44
def move(depos, offset)
Definition: depos.py:107
p
Definition: test.py:223
ProductID put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
Definition: DataViewImpl.h:686
bool CreateAssn(PRODUCER const &prod, art::Event &evt, std::vector< T > const &a, art::Ptr< U > const &b, art::Assns< U, T > &assn, std::string a_instance, size_t indx=UINT_MAX)
Creates a single one-to-one association.
void TrackProp(double TrackStart_X, double TrackEnd_X, double &TrackLength_X, double &TrackCentre_X, double TrackStart_Y, double TrackEnd_Y, double &TrackLength_Y, double &TrackCentre_Y, double TrackStart_Z, double TrackEnd_Z, double &TrackLength_Z, double &TrackCentre_Z, double trkTimeStart, double trkTimeEnd, double &trkTimeLengh, double &trkTimeCentre, double &TrackLength)
double distance(double x1, double y1, double z1, double x2, double y2, double z2)
Declaration of signal hit object.
PhotonCounterT0Matching(fhicl::ParameterSet const &p)
tracking::Point_t Point_t
Definition: Track.h:53
Provides recob::Track data product.
PhotonCounterT0Matching & operator=(PhotonCounterT0Matching const &)=delete
TCEvent evt
Definition: DataStructs.cxx:7
void fill_ptr_vector(std::vector< Ptr< T >> &ptrs, H const &h)
Definition: Ptr.h:297
QTextStream & endl(QTextStream &s)