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