All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TrackAna_module.cc
Go to the documentation of this file.
1 //
2 // Name: TrackAna_module.cc
3 //
4 // Purpose: Module TrackAna.
5 //
6 // Configuration parameters.
7 //
8 // TrackModuleLabel: Track module label.
9 // MCTrackModuleLabel: MCTrack module label.
10 // MinMCKE: Minimum MC particle kinetic energy.
11 // MatchColinearity: Minimum colinearity for mc-track matching.
12 // MatchDisp: Maximum uv displacement for mc-track matching.
13 // WMatchDisp: maximum w displacement for mc-track matching.
14 // MatchLength: Minimum length fraction for mc-track matching.
15 //
16 // Created: 2-Aug-2011 H. Greenlee
17 //
18 
19 #include <cmath>
20 #include <iomanip>
21 #include <iostream>
22 #include <map>
23 #include <memory>
24 #include <sstream>
25 
26 #include "art/Framework/Core/EDAnalyzer.h"
27 #include "art/Framework/Core/ModuleMacros.h"
28 #include "art/Framework/Principal/Event.h"
29 #include "art/Framework/Services/Registry/ServiceHandle.h"
30 #include "art_root_io/TFileService.h"
31 #include "canvas/Persistency/Common/FindManyP.h"
32 #include "cetlib_except/exception.h"
33 #include "messagefacility/MessageLogger/MessageLogger.h"
34 
45 #include "nusimdata/SimulationBase/MCParticle.h"
46 
47 #include "TH1F.h"
48 #include "TH2F.h"
49 #include "TMatrixD.h"
50 
51 namespace {
52 
53  // Calculate distance to boundary.
54  //----------------------------------------------------------------------------
55  double
56  bdist(const TVector3& pos, unsigned int /*tpc*/ = 0, unsigned int /*cstat*/ = 0)
57  {
58  // Get geometry.
59 
60  art::ServiceHandle<geo::Geometry const> geom;
61 
62  double d1 = pos.X(); // Distance to right side (wires).
63  double d2 = 2. * geom->DetHalfWidth() - pos.X(); // Distance to left side (cathode).
64  double d3 = pos.Y() + geom->DetHalfHeight(); // Distance to bottom.
65  double d4 = geom->DetHalfHeight() - pos.Y(); // Distance to top.
66  double d5 = pos.Z(); // Distance to front.
67  double d6 = geom->DetLength() - pos.Z(); // Distance to back.
68 
69  return std::min({d1, d2, d3, d4, d5, d6});
70  }
71 
72  // Length of reconstructed track.
73  //----------------------------------------------------------------------------
74  double
75  length(const recob::Track& track)
76  {
77  return track.Length();
78  }
79 
80  // Length of MC particle.
81  //----------------------------------------------------------------------------
82  double
83  length(detinfo::DetectorClocksData const& clockData,
85  const simb::MCParticle& part,
86  double dx,
87  TVector3& start,
88  TVector3& end,
89  TVector3& startmom,
90  TVector3& endmom)
91  {
92  art::ServiceHandle<geo::Geometry const> geom;
93 
94  // Get fiducial volume boundary.
95  double xmin = 0.;
96  double xmax = 2. * geom->DetHalfWidth();
97  double ymin = -geom->DetHalfHeight();
98  double ymax = geom->DetHalfHeight();
99  double zmin = 0.;
100  double zmax = geom->DetLength();
101  double result = 0.;
102  TVector3 disp;
103  int n = part.NumberTrajectoryPoints();
104  bool first = true;
105 
106  for (int i = 0; i < n; ++i) {
107  TVector3 pos = part.Position(i).Vect();
108 
109  // Make fiducial cuts. Require the particle to be within the physical volume of
110  // the tpc, and also require the apparent x position to be within the expanded
111  // readout frame.
112 
113  if (pos.X() >= xmin && pos.X() <= xmax && pos.Y() >= ymin && pos.Y() <= ymax &&
114  pos.Z() >= zmin && pos.Z() <= zmax) {
115  pos[0] += dx;
116  double ticks = detProp.ConvertXToTicks(pos[0], 0, 0, 0);
117  if (ticks >= 0. && ticks < detProp.ReadOutWindowSize()) {
118  if (first) {
119  start = pos;
120  startmom = part.Momentum(i).Vect();
121  }
122  else {
123  disp -= pos;
124  result += disp.Mag();
125  }
126  first = false;
127  disp = pos;
128  end = pos;
129  endmom = part.Momentum(i).Vect();
130  }
131  }
132  }
133 
134  return result;
135  }
136 
137  // Length of MCTrack.
138  // In this function, the extracted start and end momenta are converted to GeV
139  // (MCTrack stores momenta in Mev).
140  //----------------------------------------------------------------------------
141  double
142  length(detinfo::DetectorClocksData const& clockData,
143  detinfo::DetectorPropertiesData const& detProp,
144  const sim::MCTrack& mctrk,
145  double dx,
146  TVector3& start,
147  TVector3& end,
148  TVector3& startmom,
149  TVector3& endmom)
150  {
151  art::ServiceHandle<geo::Geometry const> geom;
152 
153  // Get fiducial volume boundary.
154 
155  double xmin = 0.;
156  double xmax = 2. * geom->DetHalfWidth();
157  double ymin = -geom->DetHalfHeight();
158  double ymax = geom->DetHalfHeight();
159  double zmin = 0.;
160  double zmax = geom->DetLength();
161  double result = 0.;
162  TVector3 disp;
163  int n = mctrk.size();
164  bool first = true;
165 
166  for (int i = 0; i < n; ++i) {
167  TVector3 pos = mctrk[i].Position().Vect();
168 
169  // Make fiducial cuts. Require the particle to be within the physical volume of
170  // the tpc, and also require the apparent x position to be within the expanded
171  // readout frame.
172 
173  if (pos.X() >= xmin && pos.X() <= xmax && pos.Y() >= ymin && pos.Y() <= ymax &&
174  pos.Z() >= zmin && pos.Z() <= zmax) {
175  pos[0] += dx;
176  double ticks = detProp.ConvertXToTicks(pos[0], 0, 0, 0);
177  if (ticks >= 0. && ticks < detProp.ReadOutWindowSize()) {
178  if (first) {
179  start = pos;
180  startmom = 0.001 * mctrk[i].Momentum().Vect();
181  }
182  else {
183  disp -= pos;
184  result += disp.Mag();
185  }
186  first = false;
187  disp = pos;
188  end = pos;
189  endmom = 0.001 * mctrk[i].Momentum().Vect();
190  }
191  }
192  }
193 
194  return result;
195  }
196 
197  // Fill efficiency histogram assuming binomial errors.
198 
199  void
200  effcalc(const TH1* hnum, const TH1* hden, TH1* heff)
201  {
202  int nbins = hnum->GetNbinsX();
203  if (nbins != hden->GetNbinsX())
204  throw cet::exception("TrackAna") << "effcalc[" __FILE__ "]: incompatible histograms (I)\n";
205  if (nbins != heff->GetNbinsX())
206  throw cet::exception("TrackAna") << "effcalc[" __FILE__ "]: incompatible histograms (II)\n";
207 
208  // Loop over bins, including underflow and overflow.
209 
210  for (int ibin = 0; ibin <= nbins + 1; ++ibin) {
211  double num = hnum->GetBinContent(ibin);
212  double den = hden->GetBinContent(ibin);
213  if (den == 0.) {
214  heff->SetBinContent(ibin, 0.);
215  heff->SetBinError(ibin, 0.);
216  }
217  else {
218  double eff = num / den;
219  if (eff < 0.) eff = 0.;
220  if (eff > 1.) eff = 1.;
221  double err = std::sqrt(eff * (1. - eff) / den);
222  heff->SetBinContent(ibin, eff);
223  heff->SetBinError(ibin, err);
224  }
225  }
226 
227  heff->SetMinimum(0.);
228  heff->SetMaximum(1.05);
229  heff->SetMarkerStyle(20);
230  }
231 
232  class flattener : public std::vector<unsigned int> {
233 
234  public:
235  flattener() : std::vector<unsigned int>(){};
236 
237  flattener(const std::vector<std::vector<unsigned int>>& input) { Convert(input); }
238 
239  ~flattener() {}
240 
241  void
242  Convert(const std::vector<std::vector<unsigned int>>& input)
243  {
244  clear();
245  size_t length = 0;
246  for (auto const& vec : input)
247  length += vec.size();
248  reserve(length);
249 
250  for (auto const& vec : input)
251  for (auto const& value : vec)
252  push_back(value);
253  }
254  }; // end class flattener
255 
256 } // end namespace
257 
258 namespace trkf {
259 
260  class TrackAna : public art::EDAnalyzer {
261  public:
262  // Embedded structs.
263 
264  // Struct for histograms that depend on reco track only.
265 
266  struct RecoHists {
267  explicit RecoHists(const std::string& subdir);
268 
269  // Pure reco track histograms.
270 
271  TH1F* fHstartx{nullptr}; // Starting x position.
272  TH1F* fHstarty{nullptr}; // Starting y position.
273  TH1F* fHstartz{nullptr}; // Starting z position.
274  TH1F* fHstartd{nullptr}; // Starting distance to boundary.
275  TH1F* fHendx{nullptr}; // Ending x position.
276  TH1F* fHendy{nullptr}; // Ending y position.
277  TH1F* fHendz{nullptr}; // Ending z position.
278  TH1F* fHendd{nullptr}; // Ending distance to boundary.
279  TH1F* fHtheta{nullptr}; // Theta.
280  TH1F* fHphi{nullptr}; // Phi.
281  TH1F* fHtheta_xz{nullptr}; // Theta_xz.
282  TH1F* fHtheta_yz{nullptr}; // Theta_yz.
283  TH1F* fHmom{nullptr}; // Momentum.
284  TH1F* fHmoml{nullptr}; // Momentum (low momentum).
285  TH1F* fHlen{nullptr}; // Length.
286  TH1F* fHlens{nullptr}; // Length (short tracks).
287 
288  // Histograms for the consituent Hits
289 
290  TH1F* fHHitChg{nullptr}; // hit charge
291  TH1F* fHHitWidth{nullptr}; // hit width
292  TH1F* fHHitPdg{nullptr}; // Pdg primarily responsible.
293  TH1F* fHHitTrkId{nullptr}; // TrkId
294  TH1F* fModeFrac{nullptr}; // mode fraction
295  TH1F* fNTrkIdTrks{nullptr}; // # of stitched tracks in which unique TrkId appears
296  TH2F* fNTrkIdTrks2{nullptr};
297  TH2F* fNTrkIdTrks3{nullptr};
298  };
299 
300  // Struct for mc particles and mc-matched tracks.
301 
302  struct MCHists {
303  explicit MCHists(const std::string& subdir);
304 
305  // Reco-MC matching.
306 
307  TH2F* fHduvcosth{nullptr}; // 2D mc vs. data matching, duv vs. cos(theta).
308  TH1F* fHcosth{nullptr}; // 1D direction matching, cos(theta).
309  TH1F* fHmcu{nullptr}; // 1D endpoint truth u.
310  TH1F* fHmcv{nullptr}; // 1D endpoint truth v.
311  TH1F* fHmcw{nullptr}; // 1D endpoint truth w.
312  TH1F* fHupull{nullptr}; // 1D endpoint u pull.
313  TH1F* fHvpull{nullptr}; // 1D endpoint v pull.
314  TH1F* fHmcdudw{nullptr}; // Truth du/dw.
315  TH1F* fHmcdvdw{nullptr}; // Truth dv/dw.
316  TH1F* fHdudwpull{nullptr}; // du/dw pull.
317  TH1F* fHdvdwpull{nullptr}; // dv/dw pull.
318  TH1F* fHHitEff{nullptr}; // Hit efficiency.
319  TH1F* fHHitPurity{nullptr}; // Hit purity.
320 
321  // Histograms for matched tracks.
322 
323  TH1F* fHstartdx{nullptr}; // Start dx.
324  TH1F* fHstartdy{nullptr}; // Start dy.
325  TH1F* fHstartdz{nullptr}; // Start dz.
326  TH1F* fHenddx{nullptr}; // End dx.
327  TH1F* fHenddy{nullptr}; // End dy.
328  TH1F* fHenddz{nullptr}; // End dz.
329  TH2F* fHlvsl{nullptr}; // MC vs. reco length.
330  TH1F* fHdl{nullptr}; // Delta(length).
331  TH2F* fHpvsp{nullptr}; // MC vs. reco momentum.
332  TH2F* fHpvspc{nullptr}; // MC vs. reco momentum (contained tracks).
333  TH1F* fHdp{nullptr}; // Momentum difference.
334  TH1F* fHdpc{nullptr}; // Momentum difference (contained tracks).
335  TH1F* fHppull{nullptr}; // Momentum pull.
336  TH1F* fHppullc{nullptr}; // Momentum pull (contained tracks).
337 
338  // Pure MC particle histograms (efficiency denominator).
339 
340  TH1F* fHmcstartx{nullptr}; // Starting x position.
341  TH1F* fHmcstarty{nullptr}; // Starting y position.
342  TH1F* fHmcstartz{nullptr}; // Starting z position.
343  TH1F* fHmcendx{nullptr}; // Ending x position.
344  TH1F* fHmcendy{nullptr}; // Ending y position.
345  TH1F* fHmcendz{nullptr}; // Ending z position.
346  TH1F* fHmctheta{nullptr}; // Theta.
347  TH1F* fHmcphi{nullptr}; // Phi.
348  TH1F* fHmctheta_xz{nullptr}; // Theta_xz.
349  TH1F* fHmctheta_yz{nullptr}; // Theta_yz.
350  TH1F* fHmcmom{nullptr}; // Momentum.
351  TH1F* fHmcmoml{nullptr}; // Momentum (low momentum).
352  TH1F* fHmcke{nullptr}; // Kinetic energy.
353  TH1F* fHmckel{nullptr}; // Kinetic energy (low energy).
354  TH1F* fHmclen{nullptr}; // Length.
355  TH1F* fHmclens{nullptr}; // Length (short tracks).
356 
357  // Histograms for well-reconstructed matched tracks (efficiency numerator).
358 
359  TH1F* fHgstartx{nullptr}; // Starting x position.
360  TH1F* fHgstarty{nullptr}; // Starting y position.
361  TH1F* fHgstartz{nullptr}; // Starting z position.
362  TH1F* fHgendx{nullptr}; // Ending x position.
363  TH1F* fHgendy{nullptr}; // Ending y position.
364  TH1F* fHgendz{nullptr}; // Ending z position.
365  TH1F* fHgtheta{nullptr}; // Theta.
366  TH1F* fHgphi{nullptr}; // Phi.
367  TH1F* fHgtheta_xz{nullptr}; // Theta_xz.
368  TH1F* fHgtheta_yz{nullptr}; // Theta_yz.
369  TH1F* fHgmom{nullptr}; // Momentum.
370  TH1F* fHgmoml{nullptr}; // Momentum (low momentum).
371  TH1F* fHgke{nullptr}; // Kinetic energy.
372  TH1F* fHgkel{nullptr}; // Kinetic energy (low momentum).
373  TH1F* fHglen{nullptr}; // Length.
374  TH1F* fHglens{nullptr}; // Length (short tracks).
375 
376  // Efficiency histograms.
377 
378  TH1F* fHestartx{nullptr}; // Starting x position.
379  TH1F* fHestarty{nullptr}; // Starting y position.
380  TH1F* fHestartz{nullptr}; // Starting z position.
381  TH1F* fHeendx{nullptr}; // Ending x position.
382  TH1F* fHeendy{nullptr}; // Ending y position.
383  TH1F* fHeendz{nullptr}; // Ending z position.
384  TH1F* fHetheta{nullptr}; // Theta.
385  TH1F* fHephi{nullptr}; // Phi.
386  TH1F* fHetheta_xz{nullptr}; // Theta_xz.
387  TH1F* fHetheta_yz{nullptr}; // Theta_yz.
388  TH1F* fHemom{nullptr}; // Momentum.
389  TH1F* fHemoml{nullptr}; // Momentum (low momentum).
390  TH1F* fHeke{nullptr}; // Kinetic energy.
391  TH1F* fHekel{nullptr}; // Kinetic energy (low momentum).
392  TH1F* fHelen{nullptr}; // Length.
393  TH1F* fHelens{nullptr}; // Length (short tracks).
394  };
395 
396  // Constructors, destructor
397 
398  explicit TrackAna(fhicl::ParameterSet const& pset);
399 
400  private:
401  void analyze(const art::Event& evt) override;
402  void endJob() override;
403 
404  void anaStitch(const art::Event& evt,
405  detinfo::DetectorClocksData const& clockData,
406  detinfo::DetectorPropertiesData const& detProp);
407 
408  std::vector<size_t> fsort_indexes(const std::vector<double>& v);
409 
410  // Fcl Attributes.
411 
412  std::string fTrackModuleLabel;
413  std::string fMCTrackModuleLabel;
415  std::string fStitchModuleLabel;
418  std::string fHitModuleLabel;
419 
420  int fDump; // Number of events to dump to debug message facility.
421  double fMinMCKE; // Minimum MC particle kinetic energy (GeV).
422  double fMinMCLen; // Minimum MC particle length in tpc (cm).
423  double fMatchColinearity; // Minimum matching colinearity.
424  double fMatchDisp; // Maximum matching displacement.
425  double fWMatchDisp; // Maximum matching displacement in the w direction.
426  double fMatchLength; // Minimum length fraction.
427  bool fIgnoreSign; // Ignore sign of mc particle if true.
428  bool fStitchedAnalysis; // if true, do the whole drill-down from stitched track to assd hits
429 
430  std::string fOrigin;
432  simb::Origin_t fOriginValue;
433  int fPrintLevel; // 0 = none, 1 = event summary, 2 = track detail
434 
435  // Histograms.
436 
437  std::map<int, MCHists> fMCHistMap; // Indexed by pdg id.
438  std::map<int, RecoHists> fRecoHistMap; // Indexed by pdg id.
439 
440  // Statistics.
441 
443  };
444 
445  DEFINE_ART_MODULE(TrackAna)
446 
447  // RecoHists methods.
448 
449  TrackAna::RecoHists::RecoHists(const std::string& subdir)
450  {
451  // Get services.
452 
453  art::ServiceHandle<geo::Geometry const> geom;
454  art::ServiceHandle<art::TFileService> tfs;
455 
456  // Make histogram directory.
457 
458  art::TFileDirectory topdir = tfs->mkdir("trkana", "TrackAna histograms");
459  art::TFileDirectory dir = topdir.mkdir(subdir);
460 
461  // Book histograms.
462 
463  fHstartx = dir.make<TH1F>(
464  "xstart", "X Start Position", 100, -2. * geom->DetHalfWidth(), 4. * geom->DetHalfWidth());
465  fHstarty = dir.make<TH1F>(
466  "ystart", "Y Start Position", 100, -geom->DetHalfHeight(), geom->DetHalfHeight());
467  fHstartz = dir.make<TH1F>("zstart", "Z Start Position", 100, 0., geom->DetLength());
468  fHstartd = dir.make<TH1F>(
469  "dstart", "Start Position Distance to Boundary", 100, -10., geom->DetHalfWidth());
470  fHendx = dir.make<TH1F>(
471  "xend", "X End Position", 100, -2. * geom->DetHalfWidth(), 4. * geom->DetHalfWidth());
472  fHendy =
473  dir.make<TH1F>("yend", "Y End Position", 100, -geom->DetHalfHeight(), geom->DetHalfHeight());
474  fHendz = dir.make<TH1F>("zend", "Z End Position", 100, 0., geom->DetLength());
475  fHendd =
476  dir.make<TH1F>("dend", "End Position Distance to Boundary", 100, -10., geom->DetHalfWidth());
477  fHtheta = dir.make<TH1F>("theta", "Theta", 100, 0., 3.142);
478  fHphi = dir.make<TH1F>("phi", "Phi", 100, -3.142, 3.142);
479  fHtheta_xz = dir.make<TH1F>("theta_xz", "Theta_xz", 100, -3.142, 3.142);
480  fHtheta_yz = dir.make<TH1F>("theta_yz", "Theta_yz", 100, -3.142, 3.142);
481  fHmom = dir.make<TH1F>("mom", "Momentum", 100, 0., 10.);
482  fHmoml = dir.make<TH1F>("moml", "Momentum", 100, 0., 1.);
483  fHlen = dir.make<TH1F>("len", "Track Length", 100, 0., 1.1 * geom->DetLength());
484  fHlens = dir.make<TH1F>("lens", "Track Length", 100, 0., 0.1 * geom->DetLength());
485  fHHitChg = dir.make<TH1F>("hchg", "Hit Charge (ADC counts)", 100, 0., 4000.);
486  fHHitWidth = dir.make<TH1F>("hwid", "Hit Width (ticks)", 40, 0., 20.);
487  fHHitPdg = dir.make<TH1F>("hpdg", "Hit Pdg code", 5001, -2500.5, +2500.5);
488  fHHitTrkId = dir.make<TH1F>("htrkid", "Hit Track ID", 401, -200.5, +200.5);
489  fModeFrac =
490  dir.make<TH1F>("hmodefrac",
491  "quasi-Purity: Fraction of component tracks with the Track mode value",
492  20,
493  0.01,
494  1.01);
495  fNTrkIdTrks =
496  dir.make<TH1F>("hntrkids",
497  "quasi-Efficiency: Number of stitched tracks in which TrkId appears",
498  20,
499  0.,
500  +10.0);
501  fNTrkIdTrks2 = dir.make<TH2F>("hntrkids2",
502  "Number of stitched tracks in which TrkId appears vs KE [GeV]",
503  20,
504  0.,
505  +10.0,
506  20,
507  0.0,
508  1.5);
509  fNTrkIdTrks3 = dir.make<TH2F>("hntrkids3",
510  "MC Track vs Reco Track, wtd by nhits on Collection Plane",
511  10,
512  -0.5,
513  9.5,
514  10,
515  -0.5,
516  9.5);
517  fNTrkIdTrks3->GetXaxis()->SetTitle("Sorted-by-Descending-CPlane-Hits outer Track Number");
518  fNTrkIdTrks3->GetYaxis()->SetTitle("Sorted-by-Descending-True-Length G4Track");
519  }
520 
521  // MCHists methods.
522 
523  TrackAna::MCHists::MCHists(const std::string& subdir)
524  {
525  // Get services.
526 
527  art::ServiceHandle<geo::Geometry const> geom;
528  art::ServiceHandle<art::TFileService> tfs;
529 
530  // Make histogram directory.
531 
532  art::TFileDirectory topdir = tfs->mkdir("trkana", "TrackAna histograms");
533  art::TFileDirectory dir = topdir.mkdir(subdir);
534 
535  // Book histograms.
536 
537  fHduvcosth =
538  dir.make<TH2F>("duvcosth", "Delta(uv) vs. Colinearity", 100, 0.95, 1., 100, 0., 1.);
539  fHcosth = dir.make<TH1F>("colin", "Colinearity", 100, 0.95, 1.);
540  fHmcu = dir.make<TH1F>("mcu", "MC Truth U", 100, -5., 5.);
541  fHmcv = dir.make<TH1F>("mcv", "MC Truth V", 100, -5., 5.);
542  fHmcw = dir.make<TH1F>("mcw", "MC Truth W", 100, -20., 20.);
543  fHupull = dir.make<TH1F>("dupull", "U Pull", 100, -20., 20.);
544  fHvpull = dir.make<TH1F>("dvpull", "V Pull", 100, -20., 20.);
545  fHmcdudw = dir.make<TH1F>("mcdudw", "MC Truth U Slope", 100, -0.2, 0.2);
546  fHmcdvdw = dir.make<TH1F>("mcdvdw", "MV Truth V Slope", 100, -0.2, 0.2);
547  fHdudwpull = dir.make<TH1F>("dudwpull", "U Slope Pull", 100, -10., 10.);
548  fHdvdwpull = dir.make<TH1F>("dvdwpull", "V Slope Pull", 100, -10., 10.);
549  fHHitEff = dir.make<TH1F>("hiteff", "MC Hit Efficiency", 100, 0., 1.0001);
550  fHHitPurity = dir.make<TH1F>("hitpurity", "MC Hit Purity", 100, 0., 1.0001);
551  fHstartdx = dir.make<TH1F>("startdx", "Start Delta x", 100, -10., 10.);
552  fHstartdy = dir.make<TH1F>("startdy", "Start Delta y", 100, -10., 10.);
553  fHstartdz = dir.make<TH1F>("startdz", "Start Delta z", 100, -10., 10.);
554  fHenddx = dir.make<TH1F>("enddx", "End Delta x", 100, -10., 10.);
555  fHenddy = dir.make<TH1F>("enddy", "End Delta y", 100, -10., 10.);
556  fHenddz = dir.make<TH1F>("enddz", "End Delta z", 100, -10., 10.);
557  fHlvsl = dir.make<TH2F>("lvsl",
558  "Reco Length vs. MC Truth Length",
559  100,
560  0.,
561  1.1 * geom->DetLength(),
562  100,
563  0.,
564  1.1 * geom->DetLength());
565  fHdl = dir.make<TH1F>("dl", "Track Length Minus MC Particle Length", 100, -50., 50.);
566  fHpvsp =
567  dir.make<TH2F>("pvsp", "Reco Momentum vs. MC Truth Momentum", 100, 0., 5., 100, 0., 5.);
568  fHpvspc = dir.make<TH2F>(
569  "pvspc", "Reco Momentum vs. MC Truth Momentum (Contained Tracks)", 100, 0., 5., 100, 0., 5.);
570  fHdp = dir.make<TH1F>("dp", "Reco-MC Momentum Difference", 100, -5., 5.);
571  fHdpc = dir.make<TH1F>("dpc", "Reco-MC Momentum Difference (Contained Tracks)", 100, -5., 5.);
572  fHppull = dir.make<TH1F>("ppull", "Momentum Pull", 100, -10., 10.);
573  fHppullc = dir.make<TH1F>("ppullc", "Momentum Pull (Contained Tracks)", 100, -10., 10.);
574 
575  fHmcstartx = dir.make<TH1F>(
576  "mcxstart", "MC X Start Position", 10, -2. * geom->DetHalfWidth(), 4. * geom->DetHalfWidth());
577  fHmcstarty = dir.make<TH1F>(
578  "mcystart", "MC Y Start Position", 10, -geom->DetHalfHeight(), geom->DetHalfHeight());
579  fHmcstartz = dir.make<TH1F>("mczstart", "MC Z Start Position", 10, 0., geom->DetLength());
580  fHmcendx = dir.make<TH1F>(
581  "mcxend", "MC X End Position", 10, -2. * geom->DetHalfWidth(), 4. * geom->DetHalfWidth());
582  fHmcendy = dir.make<TH1F>(
583  "mcyend", "MC Y End Position", 10, -geom->DetHalfHeight(), geom->DetHalfHeight());
584  fHmcendz = dir.make<TH1F>("mczend", "MC Z End Position", 10, 0., geom->DetLength());
585  fHmctheta = dir.make<TH1F>("mctheta", "MC Theta", 20, 0., 3.142);
586  fHmcphi = dir.make<TH1F>("mcphi", "MC Phi", 10, -3.142, 3.142);
587  fHmctheta_xz = dir.make<TH1F>("mctheta_xz", "MC Theta_xz", 40, -3.142, 3.142);
588  fHmctheta_yz = dir.make<TH1F>("mctheta_yz", "MC Theta_yz", 40, -3.142, 3.142);
589  fHmcmom = dir.make<TH1F>("mcmom", "MC Momentum", 10, 0., 10.);
590  fHmcmoml = dir.make<TH1F>("mcmoml", "MC Momentum", 10, 0., 1.);
591  fHmcke = dir.make<TH1F>("mcke", "MC Kinetic Energy", 10, 0., 10.);
592  fHmckel = dir.make<TH1F>("mckel", "MC Kinetic Energy", 10, 0., 1.);
593  fHmclen = dir.make<TH1F>("mclen", "MC Particle Length", 10, 0., 1.1 * geom->DetLength());
594  fHmclens = dir.make<TH1F>("mclens", "MC Particle Length", 10, 0., 0.1 * geom->DetLength());
595 
596  fHgstartx = dir.make<TH1F>("gxstart",
597  "Good X Start Position",
598  10,
599  -2. * geom->DetHalfWidth(),
600  4. * geom->DetHalfWidth());
601  fHgstarty = dir.make<TH1F>(
602  "gystart", "Good Y Start Position", 10, -geom->DetHalfHeight(), geom->DetHalfHeight());
603  fHgstartz = dir.make<TH1F>("gzstart", "Good Z Start Position", 10, 0., geom->DetLength());
604  fHgendx = dir.make<TH1F>(
605  "gxend", "Good X End Position", 10, -2. * geom->DetHalfWidth(), 4. * geom->DetHalfWidth());
606  fHgendy = dir.make<TH1F>(
607  "gyend", "Good Y End Position", 10, -geom->DetHalfHeight(), geom->DetHalfHeight());
608  fHgendz = dir.make<TH1F>("gzend", "Good Z End Position", 10, 0., geom->DetLength());
609  fHgtheta = dir.make<TH1F>("gtheta", "Good Theta", 20, 0., 3.142);
610  fHgphi = dir.make<TH1F>("gphi", "Good Phi", 10, -3.142, 3.142);
611  fHgtheta_xz = dir.make<TH1F>("gtheta_xz", "Good Theta_xz", 40, -3.142, 3.142);
612  fHgtheta_yz = dir.make<TH1F>("gtheta_yz", "Good Theta_yz", 40, -3.142, 3.142);
613  fHgmom = dir.make<TH1F>("gmom", "Good Momentum", 10, 0., 10.);
614  fHgmoml = dir.make<TH1F>("gmoml", "Good Momentum", 10, 0., 1.);
615  fHgke = dir.make<TH1F>("gke", "Good Kinetic Energy", 10, 0., 10.);
616  fHgkel = dir.make<TH1F>("gkel", "Good Kinetic Energy", 10, 0., 1.);
617  fHglen = dir.make<TH1F>("glen", "Good Particle Length", 10, 0., 1.1 * geom->DetLength());
618  fHglens = dir.make<TH1F>("glens", "Good Particle Length", 10, 0., 0.1 * geom->DetLength());
619 
620  fHestartx = dir.make<TH1F>("exstart",
621  "Efficiency vs. X Start Position",
622  10,
623  -2. * geom->DetHalfWidth(),
624  4. * geom->DetHalfWidth());
625  fHestarty = dir.make<TH1F>("eystart",
626  "Efficiency vs. Y Start Position",
627  10,
628  -geom->DetHalfHeight(),
629  geom->DetHalfHeight());
630  fHestartz =
631  dir.make<TH1F>("ezstart", "Efficiency vs. Z Start Position", 10, 0., geom->DetLength());
632  fHeendx = dir.make<TH1F>("exend",
633  "Efficiency vs. X End Position",
634  10,
635  -2. * geom->DetHalfWidth(),
636  4. * geom->DetHalfWidth());
637  fHeendy = dir.make<TH1F>(
638  "eyend", "Efficiency vs. Y End Position", 10, -geom->DetHalfHeight(), geom->DetHalfHeight());
639  fHeendz = dir.make<TH1F>("ezend", "Efficiency vs. Z End Position", 10, 0., geom->DetLength());
640  fHetheta = dir.make<TH1F>("etheta", "Efficiency vs. Theta", 20, 0., 3.142);
641  fHephi = dir.make<TH1F>("ephi", "Efficiency vs. Phi", 10, -3.142, 3.142);
642  fHetheta_xz = dir.make<TH1F>("etheta_xz", "Efficiency vs. Theta_xz", 40, -3.142, 3.142);
643  fHetheta_yz = dir.make<TH1F>("etheta_yz", "Efficiency vs. Theta_yz", 40, -3.142, 3.142);
644  fHemom = dir.make<TH1F>("emom", "Efficiency vs. Momentum", 10, 0., 10.);
645  fHemoml = dir.make<TH1F>("emoml", "Efficiency vs. Momentum", 10, 0., 1.);
646  fHeke = dir.make<TH1F>("eke", "Efficiency vs. Kinetic Energy", 10, 0., 10.);
647  fHekel = dir.make<TH1F>("ekel", "Efficiency vs. Kinetic Energy", 10, 0., 1.);
648  fHelen =
649  dir.make<TH1F>("elen", "Efficiency vs. Particle Length", 10, 0., 1.1 * geom->DetLength());
650  fHelens =
651  dir.make<TH1F>("elens", "Efficiency vs. Particle Length", 10, 0., 0.1 * geom->DetLength());
652  }
653 
654  TrackAna::TrackAna(const fhicl::ParameterSet& pset)
655  //
656  // Purpose: Constructor.
657  //
658  // Arguments: pset - Module parameters.
659  //
660  : EDAnalyzer(pset)
661  , fTrackModuleLabel(pset.get<std::string>("TrackModuleLabel"))
662  , fMCTrackModuleLabel(pset.get<std::string>("MCTrackModuleLabel"))
663  , fSpacepointModuleLabel(pset.get<std::string>("SpacepointModuleLabel"))
664  , fStitchModuleLabel(pset.get<std::string>("StitchModuleLabel"))
665  , fTrkSpptAssocModuleLabel(pset.get<std::string>("TrkSpptAssocModuleLabel"))
666  , fHitSpptAssocModuleLabel(pset.get<std::string>("HitSpptAssocModuleLabel"))
667  , fHitModuleLabel(pset.get<std::string>("HitModuleLabel"))
668  , fDump(pset.get<int>("Dump"))
669  , fMinMCKE(pset.get<double>("MinMCKE"))
670  , fMinMCLen(pset.get<double>("MinMCLen"))
671  , fMatchColinearity(pset.get<double>("MatchColinearity"))
672  , fMatchDisp(pset.get<double>("MatchDisp"))
673  , fWMatchDisp(pset.get<double>("WMatchDisp"))
674  , fMatchLength(pset.get<double>("MatchLength"))
675  , fIgnoreSign(pset.get<bool>("IgnoreSign"))
676  , fStitchedAnalysis(pset.get<bool>("StitchedAnalysis", false))
677  , fOrigin(pset.get<std::string>("MCTrackOrigin", "Any"))
678  , fPrintLevel(pset.get<int>("PrintLevel", 0))
679  , fNumEvent(0)
680  {
681 
682  // Decide whether to check MCTrack origin
683  fCheckOrigin = false;
684  fOriginValue = simb::kUnknown;
685  if (fOrigin.find("Beam") != std::string::npos) {
686  fCheckOrigin = true;
687  fOriginValue = simb::kBeamNeutrino;
688  }
689  else if (fOrigin.find("Cosmic") != std::string::npos) {
690  fCheckOrigin = true;
692  }
693  else if (fOrigin.find("Super") != std::string::npos) {
694  fCheckOrigin = true;
695  fOriginValue = simb::kSuperNovaNeutrino;
696  }
697  else if (fOrigin.find("Single") != std::string::npos) {
698  fCheckOrigin = true;
699  fOriginValue = simb::kSingleParticle;
700  }
701 
702  // Report.
703 
704  mf::LogInfo("TrackAna") << "TrackAna configured with the following parameters:\n"
705  << " TrackModuleLabel = " << fTrackModuleLabel << "\n"
706  << " MCTrackModuleLabel = " << fMCTrackModuleLabel << "\n"
707  << " StitchModuleLabel = " << fStitchModuleLabel << "\n"
708  << " TrkSpptAssocModuleLabel = " << fTrkSpptAssocModuleLabel << "\n"
709  << " HitSpptAssocModuleLabel = " << fHitSpptAssocModuleLabel << "\n"
710  << " HitModuleLabel = " << fHitModuleLabel << "\n"
711  << " Dump = " << fDump << "\n"
712  << " MinMCKE = " << fMinMCKE << "\n"
713  << " MinMCLen = " << fMinMCLen << " Origin = " << fOrigin
714  << " Origin value " << fOriginValue;
715  }
716 
717  void
718  TrackAna::analyze(const art::Event& evt)
719  {
720  art::ServiceHandle<cheat::BackTrackerService const> bt_serv;
721  art::ServiceHandle<cheat::ParticleInventoryService const> pi_serv;
722  art::ServiceHandle<geo::Geometry const> geom;
723 
724  ++fNumEvent;
725 
726  // Optional dump stream.
727 
728  std::unique_ptr<mf::LogInfo> pdump;
729  if (fDump > 0) {
730  --fDump;
731  pdump = std::make_unique<mf::LogInfo>("TrackAna");
732  }
733 
734  // Make sure histograms are booked.
735 
736  bool mc = !evt.isRealData();
737 
738  // Get MCTracks.
739 
740  art::Handle<std::vector<sim::MCTrack>> mctrackh;
741  evt.getByLabel(fMCTrackModuleLabel, mctrackh);
742  // pair of MCTrack and index of matched reco track
743  std::vector<std::pair<const sim::MCTrack*, int>> selected_mctracks;
744 
745  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(evt);
746  auto const detProp =
747  art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(evt, clockData);
748 
749  if (mc && mctrackh.isValid()) {
750 
751  selected_mctracks.reserve(mctrackh->size());
752 
753  // Dump MCTracks.
754 
755  if (pdump) {
756  *pdump << "MC Tracks\n"
757  << " Id pdg x y z dx dy dz "
758  " p\n"
759  << "--------------------------------------------------------------------------------"
760  "-----------\n";
761  }
762 
763  // Loop over mc tracks, and fill histograms that depend only
764  // on mc information. Also, fill a secondary list of mc tracks
765  // that pass various selection criteria.
766 
767  for (std::vector<sim::MCTrack>::const_iterator imctrk = mctrackh->begin();
768  imctrk != mctrackh->end();
769  ++imctrk) {
770  const sim::MCTrack& mctrk = *imctrk;
771  int pdg = mctrk.PdgCode();
772  if (fIgnoreSign) pdg = std::abs(pdg);
773 
774  // Ignore everything except stable charged nonshowering particles.
775 
776  int apdg = std::abs(pdg);
777  if (apdg == 13 || // Muon
778  apdg == 211 || // Charged pion
779  apdg == 321 || // Charged kaon
780  apdg == 2212) { // (Anti)proton
781 
782  // check MC track origin?
783  if (fCheckOrigin && mctrk.Origin() != fOriginValue) continue;
784 
785  // Apply minimum energy cut.
786 
787  if (mctrk.Start().E() >= mctrk.Start().Momentum().Mag() + 1000. * fMinMCKE) {
788 
789  // Calculate the x offset due to nonzero mc particle time.
790 
791  double mctime = mctrk.Start().T(); // nsec
792  double mcdx = mctime * 1.e-3 * detProp.DriftVelocity(); // cm
793 
794  // Calculate the length of this mc particle inside the fiducial volume.
795 
796  TVector3 mcstart;
797  TVector3 mcend;
798  TVector3 mcstartmom;
799  TVector3 mcendmom;
800  double plen =
801  length(clockData, detProp, mctrk, mcdx, mcstart, mcend, mcstartmom, mcendmom);
802 
803  // Apply minimum fiducial length cut. Always reject particles that have
804  // zero length in the tpc regardless of the configured cut.
805 
806  if (plen > 0. && plen > fMinMCLen) {
807 
808  // This is a good mc particle (capable of making a track).
809 
810  selected_mctracks.push_back(std::make_pair(&mctrk, -1));
811 
812  // Dump MC particle information here.
813 
814  if (pdump) {
815  double pstart = mcstartmom.Mag();
816  double pend = mcendmom.Mag();
817  *pdump << "\nOffset" << std::setw(3) << mctrk.TrackID() << std::setw(6)
818  << mctrk.PdgCode() << " " << std::fixed << std::setprecision(2)
819  << std::setw(10) << mcdx << "\nStart " << std::setw(3) << mctrk.TrackID()
820  << std::setw(6) << mctrk.PdgCode() << " " << std::fixed
821  << std::setprecision(2) << std::setw(10) << mcstart[0] << std::setw(10)
822  << mcstart[1] << std::setw(10) << mcstart[2];
823  if (pstart > 0.) {
824  *pdump << " " << std::fixed << std::setprecision(3) << std::setw(10)
825  << mcstartmom[0] / pstart << std::setw(10) << mcstartmom[1] / pstart
826  << std::setw(10) << mcstartmom[2] / pstart;
827  }
828  else
829  *pdump << std::setw(32) << " ";
830  *pdump << std::setw(12) << std::fixed << std::setprecision(3) << pstart;
831  *pdump << "\nEnd " << std::setw(3) << mctrk.TrackID() << std::setw(6)
832  << mctrk.PdgCode() << " " << std::fixed << std::setprecision(2)
833  << std::setw(10) << mcend[0] << std::setw(10) << mcend[1] << std::setw(10)
834  << mcend[2];
835  if (pend > 0.01) {
836  *pdump << " " << std::fixed << std::setprecision(3) << std::setw(10)
837  << mcendmom[0] / pend << std::setw(10) << mcendmom[1] / pend
838  << std::setw(10) << mcendmom[2] / pend;
839  }
840  else
841  *pdump << std::setw(32) << " ";
842  *pdump << std::setw(12) << std::fixed << std::setprecision(3) << pend
843  << "\nLength: " << plen << "\n";
844  }
845 
846  // Fill histograms.
847 
848  if (fMCHistMap.count(pdg) == 0) {
849  std::ostringstream ostr;
850  ostr << "MC" << (fIgnoreSign ? "All" : (pdg > 0 ? "Pos" : "Neg")) << std::abs(pdg);
851  fMCHistMap.emplace(pdg, MCHists{ostr.str()});
852  }
853  const MCHists& mchists = fMCHistMap.at(pdg);
854 
855  double mctheta_xz = std::atan2(mcstartmom.X(), mcstartmom.Z());
856  double mctheta_yz = std::atan2(mcstartmom.Y(), mcstartmom.Z());
857  double mcmom = mcstartmom.Mag();
858  double mcmass = 0.001 * mctrk.Start().Momentum().Mag();
859  double mcke = mcmom * mcmom / (std::hypot(mcmom, mcmass) + mcmass);
860 
861  mchists.fHmcstartx->Fill(mcstart.X());
862  mchists.fHmcstarty->Fill(mcstart.Y());
863  mchists.fHmcstartz->Fill(mcstart.Z());
864  mchists.fHmcendx->Fill(mcend.X());
865  mchists.fHmcendy->Fill(mcend.Y());
866  mchists.fHmcendz->Fill(mcend.Z());
867  mchists.fHmctheta->Fill(mcstartmom.Theta());
868  mchists.fHmcphi->Fill(mcstartmom.Phi());
869  mchists.fHmctheta_xz->Fill(mctheta_xz);
870  mchists.fHmctheta_yz->Fill(mctheta_yz);
871  mchists.fHmcmom->Fill(mcmom);
872  mchists.fHmcmoml->Fill(mcmom);
873  mchists.fHmcke->Fill(mcke);
874  mchists.fHmckel->Fill(mcke);
875  mchists.fHmclen->Fill(plen);
876  mchists.fHmclens->Fill(plen);
877  }
878  }
879  }
880  }
881  } //mc
882 
883  // Get tracks and spacepoints and hits
884  art::Handle<std::vector<recob::Track>> trackh;
885  art::Handle<std::vector<art::PtrVector<recob::Track>>> trackvh;
886  art::Handle<std::vector<recob::Hit>> hith;
887 
888  evt.getByLabel(fTrackModuleLabel, trackh);
889  evt.getByLabel(fStitchModuleLabel, trackvh);
890  evt.getByLabel(fHitModuleLabel, hith);
891 
892  // Extract all hits into a vector of art::Ptrs (the format used by back tracker).
893 
894  std::vector<art::Ptr<recob::Hit>> allhits;
895  if (hith.isValid()) {
896  allhits.reserve(hith->size());
897  for (unsigned int i = 0; i < hith->size(); ++i) {
898  allhits.emplace_back(hith, i);
899  }
900  }
901 
902  // Construct FindManyP object to be used for finding track-hit associations.
903 
904  art::FindManyP<recob::Hit> tkhit_find(trackh, evt, fTrackModuleLabel);
905 
906  // This new top part of TrackAna between two long lines of ************s
907  // is particular to analyzing Stitched Tracks.
908  // *******************************************************************//
909 
910  if (trackvh.isValid() && fStitchedAnalysis) {
911  mf::LogDebug("TrackAna") << "TrackAna read " << trackvh->size()
912  << " vectors of Stitched PtrVectorsof tracks.";
913  anaStitch(evt, clockData, detProp);
914  }
915 
916  if (trackh.isValid()) {
917 
918  if (pdump) {
919  *pdump << "\nReconstructed Tracks\n"
920  << " Id MCid x y z dx dy dz "
921  " p\n"
922  << "--------------------------------------------------------------------------------"
923  "-----------\n";
924  }
925 
926  // Loop over tracks.
927 
928  int ntrack = trackh->size();
929  for (int i = 0; i < ntrack; ++i) {
930  art::Ptr<recob::Track> ptrack(trackh, i);
931  const recob::Track& track = *ptrack;
932 
933  // Extract hits associated with this track.
934 
935  std::vector<art::Ptr<recob::Hit>> trackhits;
936  tkhit_find.get(i, trackhits);
937 
938  // Calculate the x offset due to nonzero reconstructed time.
939 
940  double trackdx = 0;
941 
942  // Fill histograms involving reco tracks only.
943 
944  int ntraj = track.NumberTrajectoryPoints();
945  if (ntraj > 0) {
946  TVector3 pos = track.Vertex<TVector3>();
947  TVector3 dir = track.VertexDirection<TVector3>();
948  TVector3 end = track.End<TVector3>();
949  pos[0] += trackdx;
950  end[0] += trackdx;
951 
952  double dpos = bdist(pos);
953  double dend = bdist(end);
954  double tlen = length(track);
955  double theta_xz = std::atan2(dir.X(), dir.Z());
956  double theta_yz = std::atan2(dir.Y(), dir.Z());
957 
958  if (fRecoHistMap.count(0) == 0) fRecoHistMap.emplace(0, RecoHists{"Reco"});
959  const RecoHists& rhists = fRecoHistMap.at(0);
960 
961  rhists.fHstartx->Fill(pos.X());
962  rhists.fHstarty->Fill(pos.Y());
963  rhists.fHstartz->Fill(pos.Z());
964  rhists.fHstartd->Fill(dpos);
965  rhists.fHendx->Fill(end.X());
966  rhists.fHendy->Fill(end.Y());
967  rhists.fHendz->Fill(end.Z());
968  rhists.fHendd->Fill(dend);
969  rhists.fHtheta->Fill(dir.Theta());
970  rhists.fHphi->Fill(dir.Phi());
971  rhists.fHtheta_xz->Fill(theta_xz);
972  rhists.fHtheta_yz->Fill(theta_yz);
973 
974  double mom = 0.;
975  if (track.HasMomentum()) mom = track.VertexMomentum();
976  rhists.fHmom->Fill(mom);
977  rhists.fHmoml->Fill(mom);
978  rhists.fHlen->Fill(tlen);
979  rhists.fHlens->Fill(tlen);
980 
981  // Id of matching mc particle.
982 
983  int mcid = -1;
984 
985  // Loop over direction.
986 
987  for (int swap = 0; swap < 2; ++swap) {
988 
989  // Analyze reversed tracks only if start momentum = end momentum.
990 
991  if (swap != 0 && track.HasMomentum() &&
992  std::abs(track.VertexMomentum() - track.EndMomentum()) > 1.e-3)
993  continue;
994 
995  // Calculate the global-to-local rotation matrix.
996 
997  int start_point = (swap == 0 ? 0 : ntraj - 1);
998  TMatrixD rot = track.GlobalToLocalRotationAtPoint<TMatrixD>(start_point);
999 
1000  // Update track data for reversed case.
1001 
1002  if (swap != 0) {
1003  rot(1, 0) = -rot(1, 0);
1004  rot(2, 0) = -rot(2, 0);
1005  rot(1, 1) = -rot(1, 1);
1006  rot(2, 1) = -rot(2, 1);
1007  rot(1, 2) = -rot(1, 2);
1008  rot(2, 2) = -rot(2, 2);
1009 
1010  pos = track.End<TVector3>();
1011  dir = -track.EndDirection<TVector3>();
1012  end = track.Vertex<TVector3>();
1013  pos[0] += trackdx;
1014  end[0] += trackdx;
1015 
1016  dpos = bdist(pos);
1017  dend = bdist(end);
1018  theta_xz = std::atan2(dir.X(), dir.Z());
1019  theta_yz = std::atan2(dir.Y(), dir.Z());
1020 
1021  if (track.HasMomentum()) mom = track.EndMomentum();
1022  }
1023 
1024  // Get covariance matrix.
1025 
1026  const auto& cov = (swap == 0 ? track.VertexCovariance() : track.EndCovariance());
1027 
1028  // Loop over track-like mc particles.
1029 
1030  for (unsigned int imc = 0; imc < selected_mctracks.size(); ++imc) {
1031  const sim::MCTrack& mctrk = *selected_mctracks[imc].first;
1032  int pdg = mctrk.PdgCode();
1033  if (fIgnoreSign) pdg = std::abs(pdg);
1034  auto iMCHistMap = fMCHistMap.find(pdg);
1035  if (iMCHistMap == fMCHistMap.end())
1036  throw cet::exception("TrackAna") << "no particle with ID=" << pdg << "\n";
1037  const MCHists& mchists = iMCHistMap->second;
1038 
1039  // Calculate the x offset due to nonzero mc particle time.
1040 
1041  double mctime = mctrk.Start().T(); // nsec
1042  double mcdx = mctime * 1.e-3 * detProp.DriftVelocity(); // cm
1043 
1044  // Calculate the points where this mc particle enters and leaves the
1045  // fiducial volume, and the length in the fiducial volume.
1046 
1047  TVector3 mcstart;
1048  TVector3 mcend;
1049  TVector3 mcstartmom;
1050  TVector3 mcendmom;
1051  double plen =
1052  length(clockData, detProp, mctrk, mcdx, mcstart, mcend, mcstartmom, mcendmom);
1053 
1054  // Get the displacement of this mc particle in the global coordinate system.
1055 
1056  TVector3 mcpos = mcstart - pos;
1057 
1058  // Rotate the momentum and position to the
1059  // track-local coordinate system.
1060 
1061  TVector3 mcmoml = rot * mcstartmom;
1062  TVector3 mcposl = rot * mcpos;
1063 
1064  double colinearity = mcmoml.Z() / mcmoml.Mag();
1065 
1066  double u = mcposl.X();
1067  double v = mcposl.Y();
1068  double w = mcposl.Z();
1069 
1070  double pu = mcmoml.X();
1071  double pv = mcmoml.Y();
1072  double pw = mcmoml.Z();
1073 
1074  double dudw = pu / pw;
1075  double dvdw = pv / pw;
1076 
1077  double u0 = u - w * dudw;
1078  double v0 = v - w * dvdw;
1079  double uv0 = std::hypot(u0, v0);
1080 
1081  mchists.fHduvcosth->Fill(colinearity, uv0);
1082 
1083  if (std::abs(uv0) < fMatchDisp) {
1084 
1085  // Fill slope matching histograms.
1086 
1087  mchists.fHmcdudw->Fill(dudw);
1088  mchists.fHmcdvdw->Fill(dvdw);
1089  mchists.fHdudwpull->Fill(dudw / std::sqrt(cov(2, 2)));
1090  mchists.fHdvdwpull->Fill(dvdw / std::sqrt(cov(3, 3)));
1091  }
1092  mchists.fHcosth->Fill(colinearity);
1093  if (colinearity > fMatchColinearity) {
1094 
1095  // Fill displacement matching histograms.
1096 
1097  mchists.fHmcu->Fill(u0);
1098  mchists.fHmcv->Fill(v0);
1099  mchists.fHmcw->Fill(w);
1100  mchists.fHupull->Fill(u0 / std::sqrt(cov(0, 0)));
1101  mchists.fHvpull->Fill(v0 / std::sqrt(cov(1, 1)));
1102 
1103  if (std::abs(uv0) < fMatchDisp) {
1104 
1105  // Fill matching histograms.
1106 
1107  double mctheta_xz = std::atan2(mcstartmom.X(), mcstartmom.Z());
1108  double mctheta_yz = std::atan2(mcstartmom.Y(), mcstartmom.Z());
1109  double mcmom = mcstartmom.Mag();
1110  double mcmass = 0.001 * mctrk.Start().Momentum().Mag();
1111  double mcke = mcmom * mcmom / (std::hypot(mcmom, mcmass) + mcmass);
1112 
1113  mchists.fHstartdx->Fill(pos.X() - mcstart.X());
1114  mchists.fHstartdy->Fill(pos.Y() - mcstart.Y());
1115  mchists.fHstartdz->Fill(pos.Z() - mcstart.Z());
1116  mchists.fHenddx->Fill(end.X() - mcend.X());
1117  mchists.fHenddy->Fill(end.Y() - mcend.Y());
1118  mchists.fHenddz->Fill(end.Z() - mcend.Z());
1119  mchists.fHlvsl->Fill(plen, tlen);
1120  mchists.fHdl->Fill(tlen - plen);
1121  mchists.fHpvsp->Fill(mcmom, mom);
1122  double dp = mom - mcmom;
1123  mchists.fHdp->Fill(dp);
1124  mchists.fHppull->Fill(dp / std::sqrt(cov(4, 4)));
1125  if (std::abs(dpos) >= 5. && std::abs(dend) >= 5.) {
1126  mchists.fHpvspc->Fill(mcmom, mom);
1127  mchists.fHdpc->Fill(dp);
1128  mchists.fHppullc->Fill(dp / std::sqrt(cov(4, 4)));
1129  }
1130 
1131  // Count this track as well-reconstructed if it is matched to an
1132  // mc particle (which it is if get here), and if in addition the
1133  // starting position (w) matches and the reconstructed track length
1134  // is more than 0.5 of the mc particle trajectory length.
1135 
1136  bool good = std::abs(w) <= fWMatchDisp && tlen > fMatchLength * plen;
1137  if (good) {
1138  mcid = mctrk.TrackID();
1139 
1140  // Calculate and fill hit efficiency and purity.
1141 
1142  std::set<int> tkidset;
1143  tkidset.insert(mcid);
1144  double hiteff = bt_serv->HitCollectionEfficiency(
1145  clockData, tkidset, trackhits, allhits, geo::k3D);
1146  double hitpurity = bt_serv->HitCollectionPurity(clockData, tkidset, trackhits);
1147  mchists.fHHitEff->Fill(hiteff);
1148  mchists.fHHitPurity->Fill(hitpurity);
1149 
1150  // Fill efficiency numerator histograms.
1151 
1152  mchists.fHgstartx->Fill(mcstart.X());
1153  mchists.fHgstarty->Fill(mcstart.Y());
1154  mchists.fHgstartz->Fill(mcstart.Z());
1155  mchists.fHgendx->Fill(mcend.X());
1156  mchists.fHgendy->Fill(mcend.Y());
1157  mchists.fHgendz->Fill(mcend.Z());
1158  mchists.fHgtheta->Fill(mcstartmom.Theta());
1159  mchists.fHgphi->Fill(mcstartmom.Phi());
1160  mchists.fHgtheta_xz->Fill(mctheta_xz);
1161  mchists.fHgtheta_yz->Fill(mctheta_yz);
1162  mchists.fHgmom->Fill(mcmom);
1163  mchists.fHgmoml->Fill(mcmom);
1164  mchists.fHgke->Fill(mcke);
1165  mchists.fHgkel->Fill(mcke);
1166  mchists.fHglen->Fill(plen);
1167  mchists.fHglens->Fill(plen);
1168 
1169  // set the match flag
1170  selected_mctracks[imc].second = i;
1171 
1172  if (fPrintLevel > 0) {
1173  const simb::MCParticle* ptkl = pi_serv->TrackIdToParticle_P(mcid);
1174  float KE = ptkl->E() - ptkl->Mass();
1175  std::string KEUnits = " GeV";
1176  if (mctrk.Origin() != simb::kCosmicRay) {
1177  // MeV for low energy particles
1178  KE *= 1000;
1179  KEUnits = " MeV";
1180  }
1181  mf::LogVerbatim("TrackAna")
1182  << evt.run() << "." << evt.event() << " Match MCTkID " << std::setw(6)
1183  << mctrk.TrackID() << " Origin " << mctrk.Origin() << " PDG" << std::setw(5)
1184  << mctrk.PdgCode() << " KE" << std::setw(4) << (int)KE << KEUnits
1185  << " RecoTrkID " << track.ID() << " hitEff " << std::setprecision(2)
1186  << hiteff << " hitPur " << hitpurity;
1187  int sWire, sTick, eWire, eTick;
1188  // this won't work for DUNE
1189  for (unsigned short ipl = 0; ipl < geom->Nplanes(); ++ipl) {
1190  sWire = geom->NearestWire(mcstart, ipl, 0, 0);
1191  sTick = detProp.ConvertXToTicks(mcstart[0], ipl, 0, 0);
1192  eWire = geom->NearestWire(mcend, ipl, 0, 0);
1193  eTick = detProp.ConvertXToTicks(mcend[0], ipl, 0, 0);
1194  mf::LogVerbatim("TrackAna")
1195  << " Wire:Tick in Pln " << ipl << " W:T " << sWire << ":" << sTick
1196  << " - " << eWire << ":" << eTick;
1197  } // ipl
1198  } // fPrintLevel == 2
1199  } // good
1200  }
1201  }
1202  }
1203  }
1204 
1205  // Dump track information here.
1206 
1207  if (pdump) {
1208  TVector3 pos = track.Vertex<TVector3>();
1209  TVector3 dir = track.VertexDirection<TVector3>();
1210  TVector3 end = track.End<TVector3>();
1211  pos[0] += trackdx;
1212  end[0] += trackdx;
1213  TVector3 enddir = track.EndDirection<TVector3>();
1214  double pstart = track.VertexMomentum();
1215  double pend = track.EndMomentum();
1216  *pdump << "\nOffset" << std::setw(3) << track.ID() << std::setw(6) << mcid << " "
1217  << std::fixed << std::setprecision(2) << std::setw(10) << trackdx << "\nStart "
1218  << std::setw(3) << track.ID() << std::setw(6) << mcid << " " << std::fixed
1219  << std::setprecision(2) << std::setw(10) << pos[0] << std::setw(10) << pos[1]
1220  << std::setw(10) << pos[2];
1221  if (pstart > 0.) {
1222  *pdump << " " << std::fixed << std::setprecision(3) << std::setw(10) << dir[0]
1223  << std::setw(10) << dir[1] << std::setw(10) << dir[2];
1224  }
1225  else
1226  *pdump << std::setw(32) << " ";
1227  *pdump << std::setw(12) << std::fixed << std::setprecision(3) << pstart;
1228  *pdump << "\nEnd " << std::setw(3) << track.ID() << std::setw(6) << mcid << " "
1229  << std::fixed << std::setprecision(2) << std::setw(10) << end[0] << std::setw(10)
1230  << end[1] << std::setw(10) << end[2];
1231  if (pend > 0.01) {
1232  *pdump << " " << std::fixed << std::setprecision(3) << std::setw(10) << enddir[0]
1233  << std::setw(10) << enddir[1] << std::setw(10) << enddir[2];
1234  }
1235  else
1236  *pdump << std::setw(32) << " ";
1237  *pdump << std::setw(12) << std::fixed << std::setprecision(3) << pend
1238  << "\nLength: " << tlen << "\n";
1239  }
1240  }
1241  }
1242  } // i
1243 
1244  // print out un-matched MC tracks
1245  if (fPrintLevel > 0) {
1246  for (unsigned int imc = 0; imc < selected_mctracks.size(); ++imc) {
1247  if (selected_mctracks[imc].second >= 0) continue;
1248  const sim::MCTrack& mctrk = *selected_mctracks[imc].first;
1249  const simb::MCParticle* ptkl = pi_serv->TrackIdToParticle_P(mctrk.TrackID());
1250  float KE = ptkl->E() - ptkl->Mass();
1251  std::string KEUnits = " GeV";
1252  if (mctrk.Origin() != simb::kCosmicRay) {
1253  // MeV for low energy particles
1254  KE *= 1000;
1255  KEUnits = " MeV";
1256  }
1257  // find the start/end wire:time in each plane
1258  TVector3 mcstart, mcend, mcstartmom, mcendmom;
1259  double mcdx = mctrk.Start().T() * 1.e-3 * detProp.DriftVelocity(); // cm
1260  double plen = length(clockData, detProp, mctrk, mcdx, mcstart, mcend, mcstartmom, mcendmom);
1261  mf::LogVerbatim("TrackAna")
1262  << evt.run() << "." << evt.event() << " NoMat MCTkID " << std::setw(6) << mctrk.TrackID()
1263  << " Origin " << mctrk.Origin() << " PDG" << std::setw(5) << mctrk.PdgCode() << " KE"
1264  << std::setw(4) << (int)KE << KEUnits << " Length " << std::fixed << std::setprecision(1)
1265  << plen << " cm";
1266  if (fPrintLevel > 1) {
1267  int sWire, sTick, eWire, eTick;
1268  // this won't work for DUNE
1269  for (unsigned short ipl = 0; ipl < geom->Nplanes(); ++ipl) {
1270  sWire = geom->NearestWire(mcstart, ipl, 0, 0);
1271  sTick = detProp.ConvertXToTicks(mcstart[0], ipl, 0, 0);
1272  eWire = geom->NearestWire(mcend, ipl, 0, 0);
1273  eTick = detProp.ConvertXToTicks(mcend[0], ipl, 0, 0);
1274  mf::LogVerbatim("TrackAna") << " Wire:Tick in Pln " << ipl << " W:T " << sWire << ":"
1275  << sTick << " - " << eWire << ":" << eTick;
1276  } // ipl
1277  } // fPrintLevel > 1
1278  } // imc
1279  } // fPrintLevel > 0
1280  }
1281 
1282  void
1283  TrackAna::anaStitch(const art::Event& evt,
1284  detinfo::DetectorClocksData const& clockData,
1285  detinfo::DetectorPropertiesData const& detProp)
1286  {
1287  art::ServiceHandle<cheat::BackTrackerService const> bt_serv;
1288  art::ServiceHandle<cheat::ParticleInventoryService const> pi_serv;
1289  art::ServiceHandle<geo::Geometry const> geom;
1290 
1291  std::map<int, std::map<int, art::PtrVector<recob::Hit>>> hitmap; // trkID, otrk, hitvec
1292  std::map<int, int> KEmap; // length traveled in det [cm]?, trkID want to sort by KE
1293  bool mc = !evt.isRealData();
1294  art::Handle<std::vector<recob::Track>> trackh;
1295  art::Handle<std::vector<recob::SpacePoint>> sppth;
1296  art::Handle<std::vector<art::PtrVector<recob::Track>>> trackvh;
1297 
1298  evt.getByLabel(fTrackModuleLabel, trackh);
1299  evt.getByLabel(fSpacepointModuleLabel, sppth);
1300  evt.getByLabel(fStitchModuleLabel, trackvh);
1301  int ntv(trackvh->size());
1302 
1303  std::vector<art::PtrVector<recob::Track>>::const_iterator cti = trackvh->begin();
1304 
1305  if (trackh.isValid()) {
1306  art::FindManyP<recob::SpacePoint> fswhole(trackh, evt, fTrkSpptAssocModuleLabel);
1307  int nsppts_assnwhole = fswhole.size();
1308  std::cout << "TrackAna: Number of clumps of Spacepoints from Assn for all Tracks: "
1309  << nsppts_assnwhole << std::endl;
1310  }
1311 
1312  if (fRecoHistMap.count(0) == 0) {
1313  fRecoHistMap.emplace(0, RecoHists{"Reco"});
1314  std::cout << "\n"
1315  << "\t\t TrkAna: Fresh fRecoHistMap[0] ******* \n"
1316  << std::endl;
1317  }
1318  const RecoHists& rhistsStitched = fRecoHistMap.at(0);
1319 
1320  std::vector<std::vector<unsigned int>> NtrkIdsAll;
1321  std::vector<double> ntvsorted;
1322  hitmap.clear();
1323  KEmap.clear();
1324 
1325  // Look at the components of the stitched tracks. Grab their sppts/hits from Assns.
1326  for (int o = 0; o < ntv; ++o) // o for outer
1327  {
1328  const art::PtrVector<recob::Track> pvtrack(*(cti++));
1329  int ntrack = pvtrack.size();
1330  std::vector<std::vector<unsigned int>> NtrkId_Hit; // hit IDs in inner tracks
1331  std::vector<unsigned int> vecMode;
1332  art::FindManyP<recob::SpacePoint> fs(pvtrack, evt, fTrkSpptAssocModuleLabel);
1333 
1334  for (int i = 0; i < ntrack; ++i) {
1335 
1336  // From gdb> ptype fs, the vector of Ptr<SpacePoint>s it appears is
1337  // grabbed after fs.at(0)
1338  bool assns(true);
1339  try {
1340  // Got Spacepoints from this Track; now get Hits from those
1341  // Spacepoints.
1342 
1343  int nsppts_assn = fs.at(i).size();
1344 
1345  const auto& sppt = fs.at(i); //.at(0);
1346  // since we're in a try and worried about failure, we won't pull the following
1347  // FindManyP out of the loop.
1348  art::FindManyP<recob::Hit> fh(sppt, evt, fHitSpptAssocModuleLabel);
1349 
1350  // Importantly, loop on all sppts, though they don't all contribute to the track.
1351  // As opposed to looping on the trajectory pts, which is a lower number.
1352  // Also, important, in job in whch this runs I set TrackKal3DSPS parameter MaxPass=1,
1353  // cuz I don't want merely the sparse set of sppts as follows from the uncontained
1354  // MS-measurement in 2nd pass.
1355  std::vector<unsigned int> vecNtrkIds;
1356  for (int is = 0; is < nsppts_assn; ++is) {
1357  int nhits = fh.at(is).size(); // should be 2 or 3: number of planes.
1358  for (int ih = 0; ih < nhits; ++ih) {
1359  const auto& hit = fh.at(is).at(ih); // Our vector is after the .at(is) this time.
1360  if (hit->SignalType() != geo::kCollection) continue;
1361  rhistsStitched.fHHitChg->Fill(hit->Integral());
1362  rhistsStitched.fHHitWidth->Fill(2. * hit->RMS());
1363  if (mc) {
1364  std::vector<sim::TrackIDE> tids = bt_serv->HitToTrackIDEs(clockData, hit);
1365  // more here.
1366  // Loop over track ids.
1367  bool justOne(true); // Only take first trk that contributed to this hit
1368  for (std::vector<sim::TrackIDE>::const_iterator itid = tids.begin();
1369  itid != tids.end();
1370  ++itid) {
1371  int trackID = std::abs(itid->trackID);
1372  hitmap[trackID][o].push_back(hit);
1373 
1374  if (justOne) {
1375  vecNtrkIds.push_back(trackID);
1376  justOne = false;
1377  }
1378  // Add hit to PtrVector corresponding to this track id.
1379  rhistsStitched.fHHitTrkId->Fill(trackID);
1380  const simb::MCParticle* part = pi_serv->TrackIdToParticle_P(trackID);
1381  if (!part) break;
1382 
1383  rhistsStitched.fHHitPdg->Fill(part->PdgCode());
1384  // This really needs to be indexed as KE deposited in volTPC, not just KE. EC, 24-July-2014.
1385 
1386  TVector3 mcstart;
1387  TVector3 mcend;
1388  TVector3 mcstartmom;
1389  TVector3 mcendmom;
1390  double mctime = part->T(); // nsec
1391  double mcdx = mctime * 1.e-3 * detProp.DriftVelocity(); // cm
1392 
1393  double plen =
1394  length(clockData, detProp, *part, mcdx, mcstart, mcend, mcstartmom, mcendmom);
1395 
1396  KEmap[(int)(1e6 * plen)] = trackID; // multiple assignment but always the same, so
1397  // fine.
1398  }
1399 
1400  } // mc
1401  } // hits
1402 
1403  } // spacepoints
1404 
1405  if (mc) {
1406  NtrkId_Hit.push_back(vecNtrkIds);
1407  // Find the trkID mode for this i^th track
1408  unsigned int ii(1);
1409  int max(-12), n(1), ind(0);
1410  std::sort(vecNtrkIds.begin(), vecNtrkIds.end());
1411  std::vector<unsigned int> strkIds(vecNtrkIds);
1412  while (ii < vecNtrkIds.size()) {
1413  if (strkIds.at(ii) != strkIds.at(ii - 1)) { n = 1; }
1414  else {
1415  n++;
1416  }
1417  if (n > max) {
1418  max = n;
1419  ind = ii;
1420  }
1421  ii++;
1422  }
1423  unsigned int mode(sim::NoParticleId);
1424  if (strkIds.begin() != strkIds.end()) mode = strkIds.at(ind);
1425  vecMode.push_back(mode);
1426 
1427  if (strkIds.size() != 0)
1428  rhistsStitched.fModeFrac->Fill((double)max / (double)strkIds.size());
1429  else
1430  rhistsStitched.fModeFrac->Fill(-1.0);
1431  } // mc
1432 
1433  } // end try
1434  catch (cet::exception& x) {
1435  assns = false;
1436  }
1437  if (!assns) throw cet::exception("TrackAna") << "Bad Associations. \n";
1438 
1439  } // i
1440 
1441  if (mc) {
1442  // one vector per o trk, for all modes of stitched i trks
1443  NtrkIdsAll.push_back(vecMode);
1444 
1445  std::unique(NtrkIdsAll.back().begin(), NtrkIdsAll.back().end());
1446  double sum(0.0);
1447  for (auto const val : NtrkIdsAll.back()) {
1448  sum += hitmap[val][o].size();
1449  }
1450  ntvsorted.push_back(sum);
1451  }
1452 
1453  //
1454  } // o
1455 
1456  int vtmp(0);
1457  // get KEmap indices by most energetic first, least last.
1458  for (auto it = KEmap.rbegin(); it != KEmap.rend(); ++it) {
1459  vtmp++;
1460  }
1461 
1462  // get o trk indices by their hits. Most populous track first, least last.
1463  for (auto const o : fsort_indexes(ntvsorted)) {
1464  int v(0);
1465  // get KEmap indices by longest trajectory first, least last.
1466  for (auto it = KEmap.rbegin(); it != KEmap.rend(); ++it) {
1467  int val = it->second; // grab trkIDs in order, since they're sorted by KE
1468  rhistsStitched.fNTrkIdTrks3->Fill(o, v, hitmap[val][o].size());
1469  v++;
1470  }
1471  }
1472 
1473  // In how many o tracks did each trkId appear? Histo it. Would like it to be
1474  // precisely 1. Histo it vs. particle KE.
1475  flattener flat(NtrkIdsAll);
1476  std::vector<unsigned int>& v = flat;
1477  // auto const it ( std::unique(v.begin(),v.end()) ); // never use this it,
1478  // perhaps.
1479  for (auto const val : v) {
1480  if (val != (unsigned int)sim::NoParticleId) {
1481  const simb::MCParticle* part = pi_serv->TrackIdToParticle_P(val);
1482  double T(part->E() - 0.001 * part->Mass());
1483  rhistsStitched.fNTrkIdTrks->Fill(std::count(v.begin(), v.end(), val));
1484  rhistsStitched.fNTrkIdTrks2->Fill(std::count(v.begin(), v.end(), val), T);
1485  }
1486  else {
1487  rhistsStitched.fNTrkIdTrks2->Fill(-1.0, 0.0);
1488  }
1489  }
1490  }
1491 
1492  void
1493  TrackAna::endJob()
1494  {
1495  // Print summary.
1496 
1497  mf::LogInfo("TrackAna") << "TrackAna statistics:\n"
1498  << " Number of events = " << fNumEvent;
1499 
1500  // Fill efficiency histograms.
1501 
1502  for (std::map<int, MCHists>::const_iterator i = fMCHistMap.begin(); i != fMCHistMap.end();
1503  ++i) {
1504  const MCHists& mchists = i->second;
1505  effcalc(mchists.fHgstartx, mchists.fHmcstartx, mchists.fHestartx);
1506  effcalc(mchists.fHgstarty, mchists.fHmcstarty, mchists.fHestarty);
1507  effcalc(mchists.fHgstartz, mchists.fHmcstartz, mchists.fHestartz);
1508  effcalc(mchists.fHgendx, mchists.fHmcendx, mchists.fHeendx);
1509  effcalc(mchists.fHgendy, mchists.fHmcendy, mchists.fHeendy);
1510  effcalc(mchists.fHgendz, mchists.fHmcendz, mchists.fHeendz);
1511  effcalc(mchists.fHgtheta, mchists.fHmctheta, mchists.fHetheta);
1512  effcalc(mchists.fHgphi, mchists.fHmcphi, mchists.fHephi);
1513  effcalc(mchists.fHgtheta_xz, mchists.fHmctheta_xz, mchists.fHetheta_xz);
1514  effcalc(mchists.fHgtheta_yz, mchists.fHmctheta_yz, mchists.fHetheta_yz);
1515  effcalc(mchists.fHgmom, mchists.fHmcmom, mchists.fHemom);
1516  effcalc(mchists.fHgmoml, mchists.fHmcmoml, mchists.fHemoml);
1517  effcalc(mchists.fHgke, mchists.fHmcke, mchists.fHeke);
1518  effcalc(mchists.fHgkel, mchists.fHmckel, mchists.fHekel);
1519  effcalc(mchists.fHglen, mchists.fHmclen, mchists.fHelen);
1520  effcalc(mchists.fHglens, mchists.fHmclens, mchists.fHelens);
1521  }
1522  }
1523 
1524  // Stole this from online. Returns indices sorted by corresponding vector values.
1525  std::vector<size_t>
1526  TrackAna::fsort_indexes(const std::vector<double>& v)
1527  {
1528  // initialize original index locations
1529  std::vector<size_t> idx(v.size());
1530  for (size_t i = 0; i != idx.size(); ++i)
1531  idx[i] = i;
1532  // sort indexes based on comparing values in v
1533  std::sort(idx.begin(), idx.end(), [&v](size_t i1, size_t i2) {
1534  return v[i1] > v[i2];
1535  }); // Want most occupied trks first. was <, EC, 21-July.
1536  return idx;
1537  }
1538 
1539 }
double std(const std::vector< short > &wf, const double ped_mean, size_t start, size_t nsample)
Definition: UtilFunc.cxx:42
simb::Origin_t Origin() const
Definition: MCTrack.h:40
double VertexMomentum() const
unsigned int event
Definition: DataStructs.h:634
var pdg
Definition: selectors.fcl:14
unsigned int run
Definition: DataStructs.h:635
process_name opflash particleana ie x
std::string fHitSpptAssocModuleLabel
std::string fTrkSpptAssocModuleLabel
std::string fSpacepointModuleLabel
Declaration of signal hit object.
EResult err(const char *call)
size_t NumberTrajectoryPoints() const
Various functions related to the presence and the number of (valid) points.
Vector_t VertexDirection() const
const SMatrixSym55 & VertexCovariance() const
static constexpr bool
std::size_t size(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:561
std::string fStitchModuleLabel
TrackAna(fhicl::ParameterSet const &pset)
process_name use argoneut_mc_hitfinder track
double T() const
Definition: MCStep.h:45
process_name hit
Definition: cheaterreco.fcl:51
tick ticks
Alias for common language habits.
Definition: electronics.h:78
std::map< int, MCHists > fMCHistMap
3-dimensional objects, potentially hits, clusters, prongs, etc.
Definition: geo_types.h:135
Rotation_t GlobalToLocalRotationAtPoint(size_t p) const
process_name pandoraGausCryo1 vertexChargeCryo1 vertexStubCryo1 xmin
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
T abs(T value)
const SMatrixSym55 & EndCovariance() const
MCHists(const std::string &subdir)
double Length(size_t p=0) const
Access to various track properties.
std::vector< size_t > fsort_indexes(const std::vector< double > &v)
RecoHists(const std::string &subdir)
static const int NoParticleId
Definition: sim.h:21
const char mode
Definition: noise_ana.cxx:20
void anaStitch(const art::Event &evt, detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp)
Point_t const & Vertex() const
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
double ConvertXToTicks(double X, int p, int t, int c) const
const Cut kCosmicRay
std::string fMCTrackModuleLabel
double DriftVelocity(double efield=0., double temperature=0.) const
cm/us
Class def header for mctrack data container.
Provides recob::Track data product.
int PdgCode() const
Definition: MCTrack.h:41
void analyze(const art::Event &evt) override
const TLorentzVector & Momentum() const
Definition: MCStep.h:38
tuple dir
Definition: dropbox.py:28
simb::Origin_t fOriginValue
std::string fOrigin
Contains all timing reference information for the detector.
Vector_t EndDirection() const
std::map< int, RecoHists > fRecoHistMap
void endJob() override
do i e
double E() const
Definition: MCStep.h:49
Point_t const & End() const
const MCStep & Start() const
Definition: MCTrack.h:44
temporary value
art::ServiceHandle< art::TFileService > tfs
std::string fTrackModuleLabel
unsigned int TrackID() const
Definition: MCTrack.h:42
TCEvent evt
Definition: DataStructs.cxx:8
std::size_t count(Cont const &cont)
std::string fHitModuleLabel
Tools and modules for checking out the basics of the Monte Carlo.
art framework interface to geometry description
BEGIN_PROLOG could also be cout
auto const detProp
Track from a non-cascading particle.A recob::Track consists of a recob::TrackTrajectory, plus additional members relevant for a &quot;fitted&quot; track:
Signal from collection planes.
Definition: geo_types.h:146