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