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