LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
SeedAna_module.cc
Go to the documentation of this file.
1 //
2 // Name: SeedAna_module.cc
3 //
4 // Purpose: Module SeedAna.
5 //
6 // Configuration parameters.
7 //
8 // SeedModuleLabel: Seed module label.
9 // MCTrackModuleLabel: MCTrack module label.
10 // MinMCKE: Minimum MC particle kinetic energy.
11 // MatchColinearity: Minimum colinearity for mc-seed matching.
12 // MatchDisp: Maximum uv displacement for mc-seed 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 
28 #include "cetlib_except/exception.h"
29 
35 
36 #include "TH2F.h"
37 #include "TFile.h"
38 #include "TMatrixD.h"
39 
40 namespace {
41 
42  // Local functions.
43 
44  // Calculate distance to boundary.
45  //----------------------------------------------------------------------------
46  double bdist(const TVector3& pos, unsigned int /*tpc*/ = 0, unsigned int /*cstat*/ = 0)
47  {
48  // Get geometry.
49 
51 
52  double d1 = pos.X(); // Distance to right side (wires).
53  double d2 = 2.*geom->DetHalfWidth() - pos.X(); // Distance to left side (cathode).
54  double d3 = pos.Y() + geom->DetHalfHeight(); // Distance to bottom.
55  double d4 = geom->DetHalfHeight() - pos.Y(); // Distance to top.
56  double d5 = pos.Z(); // Distance to front.
57  double d6 = geom->DetLength() - pos.Z(); // Distance to back.
58 
59  double result = std::min(std::min(std::min(std::min(std::min(d1, d2), d3), d4), d5), d6);
60  return result;
61  }
62 
63  // Find the closest matching mc trajectory point (sim::MCStep) for a given seed.
64  // Returned value is index of the trajectory point.
65  // Return -1 in case of no match.
66  int mcmatch(const sim::MCTrack& mctrk, const recob::Seed& seed)
67  {
68  // Get seed point.
69 
70  double pos[3];
71  double err[3];
72  seed.GetPoint(pos, err);
73 
74  // Calculate the x offset due to nonzero mc particle time.
75  const detinfo::DetectorProperties* detprop = lar::providerFrom<detinfo::DetectorPropertiesService>();
76 
77  double mctime = mctrk.Start().T(); // nsec
78  double mcdx = mctime * 1.e-3 * detprop->DriftVelocity(); // cm
79 
80  // Loop over trajectory points.
81 
82  int best_traj = -1;
83  double max_dist = 0.;
84  int ntraj = mctrk.size();
85  for(int itraj = 0; itraj < ntraj; ++itraj) {
86  const TLorentzVector& vec = mctrk[itraj].Position();
87  double dx = pos[0] - vec.X() - mcdx;
88  double dy = pos[1] - vec.Y();
89  double dz = pos[2] - vec.Z();
90  double dist = std::sqrt(dx*dx + dy*dy + dz*dz);
91  if(best_traj < 0 || dist < max_dist) {
92  best_traj = itraj;
93  max_dist = dist;
94  }
95  }
96  return best_traj;
97  }
98 
99  // Length of MCTrack.
100  // In this function, the extracted start and end momenta are converted to GeV
101  // (MCTrack stores momenta in Mev).
102  //----------------------------------------------------------------------------
103  double length(const sim::MCTrack& mctrk, double dx,
104  TVector3& start, TVector3& end, TVector3& startmom, TVector3& endmom,
105  unsigned int /*tpc*/ = 0, unsigned int /*cstat*/ = 0)
106  {
107  // Get services.
108 
110  const detinfo::DetectorProperties* detprop = lar::providerFrom<detinfo::DetectorPropertiesService>();
111 
112  // Get fiducial volume boundary.
113 
114  double xmin = 0.;
115  double xmax = 2.*geom->DetHalfWidth();
116  double ymin = -geom->DetHalfHeight();
117  double ymax = geom->DetHalfHeight();
118  double zmin = 0.;
119  double zmax = geom->DetLength();
120  //double ticks_max = detprop->ReadOutWindowSize();
121  double result = 0.;
122  TVector3 disp;
123  int n = mctrk.size();
124  bool first = true;
125 
126  for(int i = 0; i < n; ++i) {
127  TVector3 pos = mctrk[i].Position().Vect();
128 
129  // Make fiducial cuts. Require the particle to be within the physical volume of
130  // the tpc, and also require the apparent x position to be within the expanded
131  // readout frame.
132 
133  if(pos.X() >= xmin &&
134  pos.X() <= xmax &&
135  pos.Y() >= ymin &&
136  pos.Y() <= ymax &&
137  pos.Z() >= zmin &&
138  pos.Z() <= zmax) {
139  pos[0] += dx;
140  double ticks = detprop->ConvertXToTicks(pos[0], 0, 0, 0);
141  if(ticks >= 0. && ticks < detprop->ReadOutWindowSize()) {
142  if(first) {
143  start = pos;
144  startmom = 0.001 * mctrk[i].Momentum().Vect();
145  }
146  else {
147  disp -= pos;
148  result += disp.Mag();
149  }
150  first = false;
151  disp = pos;
152  end = pos;
153  endmom = 0.001 * mctrk[i].Momentum().Vect();
154  }
155  }
156  }
157 
158  return result;
159  }
160 
161  // Fill efficiency histogram assuming binomial errors.
162 
163  void effcalc(const TH1* hnum, const TH1* hden, TH1* heff)
164  {
165  int nbins = hnum->GetNbinsX();
166  if (nbins != hden->GetNbinsX())
167  throw cet::exception("SeedAna") << "effcalc[" __FILE__ "]: incompatible histograms (I)\n";
168  if (nbins != heff->GetNbinsX())
169  throw cet::exception("SeedAna") << "effcalc[" __FILE__ "]: incompatible histograms (II)\n";
170 
171  // Loop over bins, including underflow and overflow.
172 
173  for(int ibin = 0; ibin <= nbins+1; ++ibin) {
174  double num = hnum->GetBinContent(ibin);
175  double den = hden->GetBinContent(ibin);
176  if(den == 0.) {
177  heff->SetBinContent(ibin, 0.);
178  heff->SetBinError(ibin, 0.);
179  }
180  else {
181  double eff = num / den;
182  if(eff < 0.)
183  eff = 0.;
184  if(eff > 1.)
185  eff = 1.;
186  double err = std::sqrt(eff * (1.-eff) / den);
187  heff->SetBinContent(ibin, eff);
188  heff->SetBinError(ibin, err);
189  }
190  }
191 
192  heff->SetMinimum(0.);
193  heff->SetMaximum(1.05);
194  heff->SetMarkerStyle(20);
195  }
196 
197  // Fill multiplicity histogram.
198 
199  void mulcalc(const TH1* hnum, const TH1* hden, TH1* hmul)
200  {
201  int nbins = hnum->GetNbinsX();
202  if (nbins != hden->GetNbinsX())
203  throw cet::exception("SeedAna") << "mulcalc[" __FILE__ "]: incompatible histograms (I)\n";
204  if (nbins != hmul->GetNbinsX())
205  throw cet::exception("SeedAna") << "mulcalc[" __FILE__ "]: incompatible histograms (II)\n";
206 
207  // Loop over bins, including underflow and overflow.
208 
209  for(int ibin = 0; ibin <= nbins+1; ++ibin) {
210  double num = hnum->GetBinContent(ibin);
211  double den = hden->GetBinContent(ibin);
212  if(den == 0.) {
213  hmul->SetBinContent(ibin, 0.);
214  hmul->SetBinError(ibin, 0.);
215  }
216  else {
217  double mul = num / den;
218  if(mul < 0.)
219  mul = 0.;
220  double err = std::sqrt((1. + mul) * mul / den);
221  hmul->SetBinContent(ibin, mul);
222  hmul->SetBinError(ibin, err);
223  }
224  }
225 
226  hmul->SetMinimum(0.);
227  hmul->SetMarkerStyle(20);
228  }
229 }
230 
231 namespace trkf {
232 
233  class SeedAna : public art::EDAnalyzer
234  {
235  public:
236 
237  // Embedded structs.
238 
239  // Struct for histograms that depend on seeds only.
240 
241  struct RecoHists
242  {
243  // Constructors.
244 
245  RecoHists();
246  RecoHists(const std::string& subdir);
247 
248  // Pure reco seed histograms.
249 
250  TH1F* fHx; // Seed x position.
251  TH1F* fHy; // Seed y position.
252  TH1F* fHz; // Seed z position.
253  TH1F* fHdist; // Seed distance to boundary.
254  TH1F* fHtheta; // Theta.
255  TH1F* fHphi; // Phi.
256  TH1F* fHtheta_xz; // Theta_xz.
257  TH1F* fHtheta_yz; // Theta_yz.
258  };
259 
260  // Struct for mc particles and mc-matched tracks.
261 
262  struct MCHists
263  {
264  // Constructors.
265 
266  MCHists();
267  MCHists(const std::string& subdir);
268 
269  // Reco-MC matching.
270 
271  TH2F* fHduvcosth; // 2D mc vs. data matching, duv vs. cos(theta).
272  TH1F* fHcosth; // 1D direction matching, cos(theta).
273  TH1F* fHmcu; // 1D endpoint truth u.
274  TH1F* fHmcv; // 1D endpoint truth v.
275  TH1F* fHmcw; // 1D endpoint truth w.
276  TH1F* fHmcdudw; // Truth du/dw.
277  TH1F* fHmcdvdw; // Truth dv/dw.
278 
279  // Pure MC particle histograms (efficiency denominator).
280 
281  TH1F* fHmcstartx; // Starting x position.
282  TH1F* fHmcstarty; // Starting y position.
283  TH1F* fHmcstartz; // Starting z position.
284  TH1F* fHmcendx; // Ending x position.
285  TH1F* fHmcendy; // Ending y position.
286  TH1F* fHmcendz; // Ending z position.
287  TH1F* fHmctheta; // Theta.
288  TH1F* fHmcphi; // Phi.
289  TH1F* fHmctheta_xz; // Theta_xz.
290  TH1F* fHmctheta_yz; // Theta_yz.
291  TH1F* fHmcmom; // Momentum.
292  TH1F* fHmclen; // Length.
293 
294  // Matched seed histograms (multiplicity numerator).
295 
296  TH1F* fHmstartx; // Starting x position.
297  TH1F* fHmstarty; // Starting y position.
298  TH1F* fHmstartz; // Starting z position.
299  TH1F* fHmendx; // Ending x position.
300  TH1F* fHmendy; // Ending y position.
301  TH1F* fHmendz; // Ending z position.
302  TH1F* fHmtheta; // Theta.
303  TH1F* fHmphi; // Phi.
304  TH1F* fHmtheta_xz; // Theta_xz.
305  TH1F* fHmtheta_yz; // Theta_yz.
306  TH1F* fHmmom; // Momentum.
307  TH1F* fHmlen; // Length.
308 
309  // Matched seed histograms (efficiency numerator).
310 
311  TH1F* fHgstartx; // Starting x position.
312  TH1F* fHgstarty; // Starting y position.
313  TH1F* fHgstartz; // Starting z position.
314  TH1F* fHgendx; // Ending x position.
315  TH1F* fHgendy; // Ending y position.
316  TH1F* fHgendz; // Ending z position.
317  TH1F* fHgtheta; // Theta.
318  TH1F* fHgphi; // Phi.
319  TH1F* fHgtheta_xz; // Theta_xz.
320  TH1F* fHgtheta_yz; // Theta_yz.
321  TH1F* fHgmom; // Momentum.
322  TH1F* fHglen; // Length.
323 
324  // Multiplicity histograms.
325 
326  TH1F* fHmulstartx; // Starting x position.
327  TH1F* fHmulstarty; // Starting y position.
328  TH1F* fHmulstartz; // Starting z position.
329  TH1F* fHmulendx; // Ending x position.
330  TH1F* fHmulendy; // Ending y position.
331  TH1F* fHmulendz; // Ending z position.
332  TH1F* fHmultheta; // Theta.
333  TH1F* fHmulphi; // Phi.
334  TH1F* fHmultheta_xz; // Theta_xz.
335  TH1F* fHmultheta_yz; // Theta_yz.
336  TH1F* fHmulmom; // Momentum.
337  TH1F* fHmullen; // Length.
338 
339  // Efficiency histograms.
340 
341  TH1F* fHestartx; // Starting x position.
342  TH1F* fHestarty; // Starting y position.
343  TH1F* fHestartz; // Starting z position.
344  TH1F* fHeendx; // Ending x position.
345  TH1F* fHeendy; // Ending y position.
346  TH1F* fHeendz; // Ending z position.
347  TH1F* fHetheta; // Theta.
348  TH1F* fHephi; // Phi.
349  TH1F* fHetheta_xz; // Theta_xz.
350  TH1F* fHetheta_yz; // Theta_yz.
351  TH1F* fHemom; // Momentum.
352  TH1F* fHelen; // Length.
353  };
354 
355  // Constructors, destructor
356 
357  explicit SeedAna(fhicl::ParameterSet const& pset);
358  virtual ~SeedAna();
359 
360  // Overrides.
361 
362  void analyze(const art::Event& evt);
363  void endJob();
364 
365  private:
366 
367  // Fcl Attributes.
368 
369  std::string fSeedModuleLabel;
370  std::string fMCTrackModuleLabel;
371  int fDump; // Number of events to dump to debug message facility.
372  double fMinMCKE; // Minimum MC particle kinetic energy (GeV).
373  double fMinMCLen; // Minimum MC particle length in tpc (cm).
374  double fMatchColinearity; // Minimum matching colinearity.
375  double fMatchDisp; // Maximum matching displacement.
376  bool fIgnoreSign; // Ignore sign of mc particle if true.
377 
378  // Histograms.
379 
380  std::map<int, MCHists> fMCHistMap; // Indexed by pdg id.
381  std::map<int, RecoHists> fRecoHistMap; // Indexed by pdg id.
382 
383  // Statistics.
384 
386  };
387 
389 
390  // RecoHists methods.
391 
393  //
394  // Purpose: Default constructor.
395  //
396  fHx(0),
397  fHy(0),
398  fHz(0),
399  fHdist(0),
400  fHtheta(0),
401  fHphi(0),
402  fHtheta_xz(0),
403  fHtheta_yz(0)
404  {}
405 
406  SeedAna::RecoHists::RecoHists(const std::string& subdir)
407  //
408  // Purpose: Initializing constructor.
409  //
410  {
411  // Make sure all histogram pointers are initially zero.
412 
413  *this = RecoHists();
414 
415  // Get services.
416 
419 
420  // Make histogram directory.
421 
422  art::TFileDirectory topdir = tfs->mkdir("seedana", "SeedAna histograms");
423  art::TFileDirectory dir = topdir.mkdir(subdir);
424 
425  // Book histograms.
426 
427  fHx = dir.make<TH1F>("x", "X Position", 100, -2.*geom->DetHalfWidth(), 4.*geom->DetHalfWidth());
428  fHy = dir.make<TH1F>("y", "Y Position", 100, -geom->DetHalfHeight(), geom->DetHalfHeight());
429  fHz = dir.make<TH1F>("z", "Z Position", 100, 0., geom->DetLength());
430  fHdist = dir.make<TH1F>("dist", "Position Distance to Boundary",
431  100, -10., geom->DetHalfWidth());
432  fHtheta = dir.make<TH1F>("theta", "Theta", 100, 0., 3.142);
433  fHphi = dir.make<TH1F>("phi", "Phi", 100, -3.142, 3.142);
434  fHtheta_xz = dir.make<TH1F>("theta_xz", "Theta_xz", 100, -3.142, 3.142);
435  fHtheta_yz = dir.make<TH1F>("theta_yz", "Theta_yz", 100, -3.142, 3.142);
436  }
437 
438  // MCHists methods.
439 
441  //
442  // Purpose: Default constructor.
443  //
444  fHduvcosth(0),
445  fHcosth(0),
446  fHmcu(0),
447  fHmcv(0),
448  fHmcw(0),
449  fHmcdudw(0),
450  fHmcdvdw(0),
451  fHmcstartx(0),
452  fHmcstarty(0),
453  fHmcstartz(0),
454  fHmcendx(0),
455  fHmcendy(0),
456  fHmcendz(0),
457  fHmctheta(0),
458  fHmcphi(0),
459  fHmctheta_xz(0),
460  fHmctheta_yz(0),
461  fHmcmom(0),
462  fHmclen(0),
463  fHmstartx(0),
464  fHmstarty(0),
465  fHmstartz(0),
466  fHmendx(0),
467  fHmendy(0),
468  fHmendz(0),
469  fHmtheta(0),
470  fHmphi(0),
471  fHmtheta_xz(0),
472  fHmtheta_yz(0),
473  fHmmom(0),
474  fHmlen(0),
475  fHgstartx(0),
476  fHgstarty(0),
477  fHgstartz(0),
478  fHgendx(0),
479  fHgendy(0),
480  fHgendz(0),
481  fHgtheta(0),
482  fHgphi(0),
483  fHgtheta_xz(0),
484  fHgtheta_yz(0),
485  fHgmom(0),
486  fHglen(0),
487  fHmulstartx(0),
488  fHmulstarty(0),
489  fHmulstartz(0),
490  fHmulendx(0),
491  fHmulendy(0),
492  fHmulendz(0),
493  fHmultheta(0),
494  fHmulphi(0),
495  fHmultheta_xz(0),
496  fHmultheta_yz(0),
497  fHmulmom(0),
498  fHmullen(0),
499  fHestartx(0),
500  fHestarty(0),
501  fHestartz(0),
502  fHeendx(0),
503  fHeendy(0),
504  fHeendz(0),
505  fHetheta(0),
506  fHephi(0),
507  fHetheta_xz(0),
508  fHetheta_yz(0),
509  fHemom(0),
510  fHelen(0)
511  {}
512 
513  SeedAna::MCHists::MCHists(const std::string& subdir)
514  //
515  // Purpose: Initializing constructor.
516  //
517  {
518  // Make sure all histogram pointers are initially zero.
519 
520  *this = MCHists();
521 
522  // Get services.
523 
526 
527  // Make histogram directory.
528 
529  art::TFileDirectory topdir = tfs->mkdir("seedana", "SeedAna histograms");
530  art::TFileDirectory dir = topdir.mkdir(subdir);
531 
532  // Book histograms.
533 
534  fHduvcosth = dir.make<TH2F>("duvcosth", "Delta(uv) vs. Colinearity",
535  100, 0.95, 1., 100, 0., 1.);
536  fHcosth = dir.make<TH1F>("colin", "Colinearity", 100, 0.95, 1.);
537  fHmcu = dir.make<TH1F>("mcu", "MC Truth U", 100, -5., 5.);
538  fHmcv = dir.make<TH1F>("mcv", "MC Truth V", 100, -5., 5.);
539  fHmcw = dir.make<TH1F>("mcw", "MC Truth W", 100, -20., 20.);
540  fHmcdudw = dir.make<TH1F>("mcdudw", "MC Truth U Slope", 100, -0.2, 0.2);
541  fHmcdvdw = dir.make<TH1F>("mcdvdw", "MV Truth V Slope", 100, -0.2, 0.2);
542 
543  fHmcstartx = dir.make<TH1F>("mcxstart", "MC X Start Position",
544  10, -2.*geom->DetHalfWidth(), 4.*geom->DetHalfWidth());
545  fHmcstarty = dir.make<TH1F>("mcystart", "MC Y Start Position",
546  10, -geom->DetHalfHeight(), geom->DetHalfHeight());
547  fHmcstartz = dir.make<TH1F>("mczstart", "MC Z Start Position",
548  10, 0., geom->DetLength());
549  fHmcendx = dir.make<TH1F>("mcxend", "MC X End Position",
550  10, -2.*geom->DetHalfWidth(), 4.*geom->DetHalfWidth());
551  fHmcendy = dir.make<TH1F>("mcyend", "MC Y End Position",
552  10, -geom->DetHalfHeight(), geom->DetHalfHeight());
553  fHmcendz = dir.make<TH1F>("mczend", "MC Z End Position",
554  10, 0., geom->DetLength());
555  fHmctheta = dir.make<TH1F>("mctheta", "MC Theta", 20, 0., 3.142);
556  fHmcphi = dir.make<TH1F>("mcphi", "MC Phi", 10, -3.142, 3.142);
557  fHmctheta_xz = dir.make<TH1F>("mctheta_xz", "MC Theta_xz", 40, -3.142, 3.142);
558  fHmctheta_yz = dir.make<TH1F>("mctheta_yz", "MC Theta_yz", 40, -3.142, 3.142);
559  fHmcmom = dir.make<TH1F>("mcmom", "MC Momentum", 10, 0., 10.);
560  fHmclen = dir.make<TH1F>("mclen", "MC Particle Length", 10, 0., 1.1 * geom->DetLength());
561 
562  fHmstartx = dir.make<TH1F>("mxstart", "Matched X Start Position",
563  10, -2.*geom->DetHalfWidth(), 4.*geom->DetHalfWidth());
564  fHmstarty = dir.make<TH1F>("mystart", "Matched Y Start Position",
565  10, -geom->DetHalfHeight(), geom->DetHalfHeight());
566  fHmstartz = dir.make<TH1F>("mzstart", "Matched Z Start Position",
567  10, 0., geom->DetLength());
568  fHmendx = dir.make<TH1F>("mxend", "Matched X End Position",
569  10, -2.*geom->DetHalfWidth(), 4.*geom->DetHalfWidth());
570  fHmendy = dir.make<TH1F>("myend", "Matched Y End Position",
571  10, -geom->DetHalfHeight(), geom->DetHalfHeight());
572  fHmendz = dir.make<TH1F>("mzend", "Matched Z End Position",
573  10, 0., geom->DetLength());
574  fHmtheta = dir.make<TH1F>("mtheta", "Matched Theta", 20, 0., 3.142);
575  fHmphi = dir.make<TH1F>("mphi", "Matched Phi", 10, -3.142, 3.142);
576  fHmtheta_xz = dir.make<TH1F>("mtheta_xz", "Matched Theta_xz", 40, -3.142, 3.142);
577  fHmtheta_yz = dir.make<TH1F>("mtheta_yz", "Matched Theta_yz", 40, -3.142, 3.142);
578  fHmmom = dir.make<TH1F>("mmom", "Matched Momentum", 10, 0., 10.);
579  fHmlen = dir.make<TH1F>("mlen", "Matched Particle Length", 10, 0., 1.1 * geom->DetLength());
580 
581  fHgstartx = dir.make<TH1F>("gxstart", "Good X Start Position",
582  10, -2.*geom->DetHalfWidth(), 4.*geom->DetHalfWidth());
583  fHgstarty = dir.make<TH1F>("gystart", "Good Y Start Position",
584  10, -geom->DetHalfHeight(), geom->DetHalfHeight());
585  fHgstartz = dir.make<TH1F>("gzstart", "Good Z Start Position",
586  10, 0., geom->DetLength());
587  fHgendx = dir.make<TH1F>("gxend", "Good X End Position",
588  10, -2.*geom->DetHalfWidth(), 4.*geom->DetHalfWidth());
589  fHgendy = dir.make<TH1F>("gyend", "Good Y End Position",
590  10, -geom->DetHalfHeight(), geom->DetHalfHeight());
591  fHgendz = dir.make<TH1F>("gzend", "Good Z End Position",
592  10, 0., geom->DetLength());
593  fHgtheta = dir.make<TH1F>("gtheta", "Good Theta", 20, 0., 3.142);
594  fHgphi = dir.make<TH1F>("gphi", "Good Phi", 10, -3.142, 3.142);
595  fHgtheta_xz = dir.make<TH1F>("gtheta_xz", "Good Theta_xz", 40, -3.142, 3.142);
596  fHgtheta_yz = dir.make<TH1F>("gtheta_yz", "Good Theta_yz", 40, -3.142, 3.142);
597  fHgmom = dir.make<TH1F>("gmom", "Good Momentum", 10, 0., 10.);
598  fHglen = dir.make<TH1F>("glen", "Good Particle Length", 10, 0., 1.1 * geom->DetLength());
599 
600  fHmulstartx = dir.make<TH1F>("mulxstart", "Multiplicity vs. X Start Position",
601  10, -2.*geom->DetHalfWidth(), 4.*geom->DetHalfWidth());
602  fHmulstarty = dir.make<TH1F>("mulystart", "Multiplicity vs. Y Start Position",
603  10, -geom->DetHalfHeight(), geom->DetHalfHeight());
604  fHmulstartz = dir.make<TH1F>("mulzstart", "Multiplicity vs. Z Start Position",
605  10, 0., geom->DetLength());
606  fHmulendx = dir.make<TH1F>("mulxend", "Multiplicity vs. X End Position",
607  10, -2.*geom->DetHalfWidth(), 4.*geom->DetHalfWidth());
608  fHmulendy = dir.make<TH1F>("mulyend", "Multiplicity vs. Y End Position",
609  10, -geom->DetHalfHeight(), geom->DetHalfHeight());
610  fHmulendz = dir.make<TH1F>("mulzend", "Multiplicity vs. Z End Position",
611  10, 0., geom->DetLength());
612  fHmultheta = dir.make<TH1F>("multheta", "Multiplicity vs. Theta", 20, 0., 3.142);
613  fHmulphi = dir.make<TH1F>("mulphi", "Multiplicity vs. Phi", 10, -3.142, 3.142);
614  fHmultheta_xz = dir.make<TH1F>("multheta_xz", "Multiplicity vs. Theta_xz", 40, -3.142, 3.142);
615  fHmultheta_yz = dir.make<TH1F>("multheta_yz", "Multiplicity vs. Theta_yz", 40, -3.142, 3.142);
616  fHmulmom = dir.make<TH1F>("mulmom", "Multiplicity vs. Momentum", 10, 0., 10.);
617  fHmullen = dir.make<TH1F>("mullen", "Multiplicity vs. Particle Length",
618  10, 0., 1.1 * geom->DetLength());
619 
620  fHestartx = dir.make<TH1F>("exstart", "Efficiency vs. X Start Position",
621  10, -2.*geom->DetHalfWidth(), 4.*geom->DetHalfWidth());
622  fHestarty = dir.make<TH1F>("eystart", "Efficiency vs. Y Start Position",
623  10, -geom->DetHalfHeight(), geom->DetHalfHeight());
624  fHestartz = dir.make<TH1F>("ezstart", "Efficiency vs. Z Start Position",
625  10, 0., geom->DetLength());
626  fHeendx = dir.make<TH1F>("exend", "Efficiency vs. X End Position",
627  10, -2.*geom->DetHalfWidth(), 4.*geom->DetHalfWidth());
628  fHeendy = dir.make<TH1F>("eyend", "Efficiency vs. Y End Position",
629  10, -geom->DetHalfHeight(), geom->DetHalfHeight());
630  fHeendz = dir.make<TH1F>("ezend", "Efficiency vs. Z End Position",
631  10, 0., geom->DetLength());
632  fHetheta = dir.make<TH1F>("etheta", "Efficiency vs. Theta", 20, 0., 3.142);
633  fHephi = dir.make<TH1F>("ephi", "Efficiency vs. Phi", 10, -3.142, 3.142);
634  fHetheta_xz = dir.make<TH1F>("etheta_xz", "Efficiency vs. Theta_xz", 40, -3.142, 3.142);
635  fHetheta_yz = dir.make<TH1F>("etheta_yz", "Efficiency vs. Theta_yz", 40, -3.142, 3.142);
636  fHemom = dir.make<TH1F>("emom", "Efficiency vs. Momentum", 10, 0., 10.);
637  fHelen = dir.make<TH1F>("elen", "Efficiency vs. Particle Length",
638  10, 0., 1.1 * geom->DetLength());
639  }
640 
642  //
643  // Purpose: Constructor.
644  //
645  // Arguments: pset - Module parameters.
646  //
647  : EDAnalyzer(pset)
648  , fSeedModuleLabel(pset.get<std::string>("SeedModuleLabel"))
649  , fMCTrackModuleLabel(pset.get<std::string>("MCTrackModuleLabel"))
650  , fDump(pset.get<int>("Dump"))
651  , fMinMCKE(pset.get<double>("MinMCKE"))
652  , fMinMCLen(pset.get<double>("MinMCLen"))
653  , fMatchColinearity(pset.get<double>("MatchColinearity"))
654  , fMatchDisp(pset.get<double>("MatchDisp"))
655  , fIgnoreSign(pset.get<bool>("IgnoreSign"))
656  , fNumEvent(0)
657  {
658 
659  // Report.
660 
661  mf::LogInfo("SeedAna")
662  << "SeedAna configured with the following parameters:\n"
663  << " SeedModuleLabel = " << fSeedModuleLabel << "\n"
664  << " MCTrackModuleLabel = " << fMCTrackModuleLabel << "\n"
665  << " Dump = " << fDump << "\n"
666  << " MinMCKE = " << fMinMCKE << "\n"
667  << " MinMCLen = " << fMinMCLen;
668  }
669 
671  //
672  // Purpose: Destructor.
673  //
674  {}
675 
676  void SeedAna::analyze(const art::Event& evt)
677  //
678  // Purpose: Analyze method.
679  //
680  // Arguments: event - Art event.
681  //
682  {
683  ++fNumEvent;
684 
685  // Optional dump stream.
686 
687  std::unique_ptr<mf::LogInfo> pdump;
688  if(fDump > 0) {
689  --fDump;
690  pdump = std::unique_ptr<mf::LogInfo>(new mf::LogInfo("TrackAna"));
691  }
692 
693  // Make sure histograms are booked.
694 
695  bool mc = !evt.isRealData();
696 
697  // Get seed handle.
698 
700  evt.getByLabel(fSeedModuleLabel, seedh);
701 
702  const detinfo::DetectorProperties* detprop = lar::providerFrom<detinfo::DetectorPropertiesService>();
703 
704  // Seed->mc track matching map.
705 
706  std::map<const recob::Seed*, int> seedmap;
707 
708  if(mc) {
709 
710  // Get MCTracks.
711 
713  evt.getByLabel(fMCTrackModuleLabel, mctrackh);
714 
715  // Dump MCTracks.
716 
717  if(pdump) {
718  *pdump << "MC Tracks\n"
719  << " Id pdg x y z dx dy dz p\n"
720  << "-------------------------------------------------------------------------------------------\n";
721  }
722 
723  // Loop over mc tracks, and fill histograms that depend only
724  // on mc particles.
725 
726  for(std::vector<sim::MCTrack>::const_iterator imctrk = mctrackh->begin();
727  imctrk != mctrackh->end(); ++imctrk) {
728  const sim::MCTrack& mctrk = *imctrk;
729  int pdg = mctrk.PdgCode();
730  if(fIgnoreSign)
731  pdg = std::abs(pdg);
732 
733  // Ignore everything except stable charged nonshowering particles.
734 
735  int apdg = std::abs(pdg);
736  if(apdg == 13 || // Muon
737  apdg == 211 || // Charged pion
738  apdg == 321 || // Charged kaon
739  apdg == 2212) { // (Anti)proton
740 
741  // Apply minimum energy cut.
742 
743  if(mctrk.Start().E() >= mctrk.Start().Momentum().Mag() + 1000.*fMinMCKE) {
744 
745  // Calculate the x offset due to nonzero mc particle time.
746 
747  double mctime = mctrk.Start().T(); // nsec
748  double mcdx = mctime * 1.e-3 * detprop->DriftVelocity(); // cm
749 
750  // Calculate the length of this mc particle inside the fiducial volume.
751 
752  TVector3 mcstart;
753  TVector3 mcend;
754  TVector3 mcstartmom;
755  TVector3 mcendmom;
756  double plen = length(mctrk, mcdx, mcstart, mcend, mcstartmom, mcendmom);
757 
758  // Apply minimum fiducial length cut. Always reject particles that have
759  // zero length in the tpc regardless of the configured cut.
760 
761  if(plen > 0. && plen > fMinMCLen) {
762 
763  // Dump MC particle information here.
764 
765  if(pdump) {
766  double pstart = mcstartmom.Mag();
767  double pend = mcendmom.Mag();
768  *pdump << "\nOffset"
769  << std::setw(3) << mctrk.TrackID()
770  << std::setw(6) << mctrk.PdgCode()
771  << " "
772  << std::fixed << std::setprecision(2)
773  << std::setw(10) << mcdx
774  << "\nStart "
775  << std::setw(3) << mctrk.TrackID()
776  << std::setw(6) << mctrk.PdgCode()
777  << " "
778  << std::fixed << std::setprecision(2)
779  << std::setw(10) << mcstart[0]
780  << std::setw(10) << mcstart[1]
781  << std::setw(10) << mcstart[2];
782  if(pstart > 0.) {
783  *pdump << " "
784  << std::fixed << std::setprecision(3)
785  << std::setw(10) << mcstartmom[0]/pstart
786  << std::setw(10) << mcstartmom[1]/pstart
787  << std::setw(10) << mcstartmom[2]/pstart;
788  }
789  else
790  *pdump << std::setw(32) << " ";
791  *pdump << std::setw(12) << std::fixed << std::setprecision(3) << pstart;
792  *pdump << "\nEnd "
793  << std::setw(3) << mctrk.TrackID()
794  << std::setw(6) << mctrk.PdgCode()
795  << " "
796  << std::fixed << std::setprecision(2)
797  << std::setw(10) << mcend[0]
798  << std::setw(10) << mcend[1]
799  << std::setw(10) << mcend[2];
800  if(pend > 0.01) {
801  *pdump << " "
802  << std::fixed << std::setprecision(3)
803  << std::setw(10) << mcendmom[0]/pend
804  << std::setw(10) << mcendmom[1]/pend
805  << std::setw(10) << mcendmom[2]/pend;
806  }
807  else
808  *pdump << std::setw(32)<< " ";
809  *pdump << std::setw(12) << std::fixed << std::setprecision(3) << pend << "\n";
810  }
811 
812  // Fill histograms.
813 
814  if(fMCHistMap.count(pdg) == 0) {
815  std::ostringstream ostr;
816  ostr << "MC" << (fIgnoreSign ? "All" : (pdg > 0 ? "Pos" : "Neg")) << std::abs(pdg);
817  fMCHistMap[pdg] = MCHists(ostr.str());
818  }
819  const MCHists& mchists = fMCHistMap[pdg];
820 
821  double mctheta_xz = std::atan2(mcstartmom.X(), mcstartmom.Z());
822  double mctheta_yz = std::atan2(mcstartmom.Y(), mcstartmom.Z());
823 
824  mchists.fHmcstartx->Fill(mcstart.X());
825  mchists.fHmcstarty->Fill(mcstart.Y());
826  mchists.fHmcstartz->Fill(mcstart.Z());
827  mchists.fHmcendx->Fill(mcend.X());
828  mchists.fHmcendy->Fill(mcend.Y());
829  mchists.fHmcendz->Fill(mcend.Z());
830  mchists.fHmctheta->Fill(mcstartmom.Theta());
831  mchists.fHmcphi->Fill(mcstartmom.Phi());
832  mchists.fHmctheta_xz->Fill(mctheta_xz);
833  mchists.fHmctheta_yz->Fill(mctheta_yz);
834  mchists.fHmcmom->Fill(mcstartmom.Mag());
835  mchists.fHmclen->Fill(plen);
836 
837  // Loop over seeds and do matching.
838 
839  int nmatch = 0;
840  if(seedh.isValid()) {
841 
842  // Loop over seeds.
843 
844  int nseed = seedh->size();
845  for(int i = 0; i < nseed; ++i) {
846  art::Ptr<recob::Seed> pseed(seedh, i);
847  const recob::Seed& seed = *pseed;
848  if(seedmap.count(&seed) == 0)
849  seedmap[&seed] = -1;
850 
851  // Get parameters of this seed.
852 
853  TVector3 pos;
854  TVector3 dir;
855  double err[3];
856  seed.GetPoint(&pos[0], err);
857  seed.GetDirection(&dir[0], err);
858 
859  // Calculate the global-to-local rotation matrix.
860  // Copied from Track.cxx.
861 
862  TMatrixD rot(3,3);
863  double dirmag = dir.Mag();
864  double diryz = std::sqrt(dir.Y()*dir.Y() + dir.Z()*dir.Z());
865 
866  double sinth = dir.X() / dirmag;
867  double costh = diryz / dirmag;
868  double sinphi = 0.;
869  double cosphi = 1.;
870  if(diryz != 0) {
871  sinphi = -dir.Y() / diryz;
872  cosphi = dir.Z() / diryz;
873  }
874  rot(0,0) = costh;
875  rot(1,0) = 0.;
876  rot(2,0) = sinth;
877  rot(0,1) = sinth * sinphi;
878  rot(1,1) = cosphi;
879  rot(2,1) = -costh * sinphi;
880  rot(0,2) = -sinth * cosphi;
881  rot(1,2) = sinphi;
882  rot(2,2) = costh * cosphi;
883 
884  // Get best matching mc trajectory point.
885 
886  int itraj = mcmatch(mctrk, seed);
887  if(itraj >= 0) {
888 
889  // Get mc relative position and direction at matching trajectory point.
890 
891  TVector3 mcpos = mctrk[itraj].Position().Vect() - pos;
892  TVector3 mcmom = mctrk[itraj].Momentum().Vect();
893  mcpos[0] += mcdx;
894 
895  // Rotate the momentum and position to the
896  // seed-local coordinate system.
897 
898  TVector3 mcmoml = rot * mcmom;
899  TVector3 mcposl = rot * mcpos;
900 
901  if(mcmoml.Z() < 0.)
902  mcmoml = -mcmoml;
903  double costh = mcmoml.Z() / mcmoml.Mag();
904 
905  double u = mcposl.X();
906  double v = mcposl.Y();
907  double w = mcposl.Z();
908 
909  double pu = mcmoml.X();
910  double pv = mcmoml.Y();
911  double pw = mcmoml.Z();
912 
913  double dudw = pu / pw;
914  double dvdw = pv / pw;
915 
916  double u0 = u - w * dudw;
917  double v0 = v - w * dvdw;
918  double uv0 = std::sqrt(u0*u0 + v0*v0);
919 
920  // Fill matching histograms.
921 
922  mchists.fHduvcosth->Fill(costh, uv0);
923  if(std::abs(uv0) < fMatchDisp) {
924 
925  // Fill slope matching histograms.
926 
927  mchists.fHmcdudw->Fill(dudw);
928  mchists.fHmcdvdw->Fill(dvdw);
929  }
930  mchists.fHcosth->Fill(costh);
931  if(costh > fMatchColinearity) {
932 
933  // Fill displacement matching histograms.
934 
935  mchists.fHmcu->Fill(u0);
936  mchists.fHmcv->Fill(v0);
937  mchists.fHmcw->Fill(w);
938 
939  if(std::abs(uv0) < fMatchDisp) {
940 
941  // Now we have passed all matching cuts and we have a matching
942  // mc particle + seed pair.
943 
944  ++nmatch;
945  seedmap[&seed] = mctrk.TrackID();
946 
947  // Fill matched seed histograms (seed multiplicity).
948 
949  mchists.fHmstartx->Fill(mcstart.X());
950  mchists.fHmstarty->Fill(mcstart.Y());
951  mchists.fHmstartz->Fill(mcstart.Z());
952  mchists.fHmendx->Fill(mcend.X());
953  mchists.fHmendy->Fill(mcend.Y());
954  mchists.fHmendz->Fill(mcend.Z());
955  mchists.fHmtheta->Fill(mcstartmom.Theta());
956  mchists.fHmphi->Fill(mcstartmom.Phi());
957  mchists.fHmtheta_xz->Fill(mctheta_xz);
958  mchists.fHmtheta_yz->Fill(mctheta_yz);
959  mchists.fHmmom->Fill(mcstartmom.Mag());
960  mchists.fHmlen->Fill(plen);
961  }
962  }
963  }
964  }
965 
966  // If we found at least one matched seed, fill good
967  // particle histograms.
968 
969  if(nmatch > 0) {
970  mchists.fHgstartx->Fill(mcstart.X());
971  mchists.fHgstarty->Fill(mcstart.Y());
972  mchists.fHgstartz->Fill(mcstart.Z());
973  mchists.fHgendx->Fill(mcend.X());
974  mchists.fHgendy->Fill(mcend.Y());
975  mchists.fHgendz->Fill(mcend.Z());
976  mchists.fHgtheta->Fill(mcstartmom.Theta());
977  mchists.fHgphi->Fill(mcstartmom.Phi());
978  mchists.fHgtheta_xz->Fill(mctheta_xz);
979  mchists.fHgtheta_yz->Fill(mctheta_yz);
980  mchists.fHgmom->Fill(mcstartmom.Mag());
981  mchists.fHglen->Fill(plen);
982  }
983  }
984  }
985  }
986  }
987  }
988  }
989 
990  // Loop over seeds and fill reco-only seed histograms.
991 
992  if(seedh.isValid()) {
993 
994  // Loop over seeds.
995 
996  int nseed = seedh->size();
997 
998  if(nseed > 0 && pdump != 0) {
999  *pdump << "\nReconstructed Seeds\n"
1000  << " MCid x y z dx dy dz p\n"
1001  << "-------------------------------------------------------------------------------------------\n";
1002  }
1003 
1004  for(int i = 0; i < nseed; ++i) {
1005  art::Ptr<recob::Seed> pseed(seedh, i);
1006  const recob::Seed& seed = *pseed;
1007 
1008  // Fill histograms involving reco seeds only.
1009 
1010  TVector3 pos;
1011  TVector3 dir;
1012  double err[3];
1013  seed.GetPoint(&pos[0], err);
1014  seed.GetDirection(&dir[0], err);
1015  double mdir = dir.Mag();
1016  if(mdir != 0.) {
1017  dir *= (1./mdir);
1018  }
1019 
1020  double dpos = bdist(pos);
1021  double theta_xz = std::atan2(dir.X(), dir.Z());
1022  double theta_yz = std::atan2(dir.Y(), dir.Z());
1023 
1024  // Dump seed information here.
1025 
1026  if(pdump) {
1027  int mcid = seedmap[&seed];
1028  *pdump << std::setw(15) << mcid
1029  << " "
1030  << std::fixed << std::setprecision(2)
1031  << std::setw(10) << pos[0]
1032  << std::setw(10) << pos[1]
1033  << std::setw(10) << pos[2]
1034  << " "
1035  << std::fixed << std::setprecision(3)
1036  << std::setw(10) << dir[0]
1037  << std::setw(10) << dir[1]
1038  << std::setw(10) << dir[2]
1039  << "\n";
1040  }
1041 
1042  // Fill histograms.
1043 
1044  if(fRecoHistMap.count(0) == 0)
1045  fRecoHistMap[0] = RecoHists("Reco");
1046  const RecoHists& rhists = fRecoHistMap[0];
1047 
1048  rhists.fHx->Fill(pos.X());
1049  rhists.fHy->Fill(pos.Y());
1050  rhists.fHz->Fill(pos.Z());
1051  rhists.fHdist->Fill(dpos);
1052  rhists.fHtheta->Fill(dir.Theta());
1053  rhists.fHphi->Fill(dir.Phi());
1054  rhists.fHtheta_xz->Fill(theta_xz);
1055  rhists.fHtheta_yz->Fill(theta_yz);
1056  }
1057  }
1058  }
1059 
1061  //
1062  // Purpose: End of job.
1063  //
1064  {
1065  // Print summary.
1066 
1067  mf::LogInfo("SeedAna")
1068  << "SeedAna statistics:\n"
1069  << " Number of events = " << fNumEvent;
1070 
1071  // Fill multiplicity histograms.
1072 
1074  i != fMCHistMap.end(); ++i) {
1075  const MCHists& mchists = i->second;
1076  mulcalc(mchists.fHmstartx, mchists.fHmcstartx, mchists.fHmulstartx);
1077  mulcalc(mchists.fHmstarty, mchists.fHmcstarty, mchists.fHmulstarty);
1078  mulcalc(mchists.fHmstartz, mchists.fHmcstartz, mchists.fHmulstartz);
1079  mulcalc(mchists.fHmendx, mchists.fHmcendx, mchists.fHmulendx);
1080  mulcalc(mchists.fHmendy, mchists.fHmcendy, mchists.fHmulendy);
1081  mulcalc(mchists.fHmendz, mchists.fHmcendz, mchists.fHmulendz);
1082  mulcalc(mchists.fHmtheta, mchists.fHmctheta, mchists.fHmultheta);
1083  mulcalc(mchists.fHmphi, mchists.fHmcphi, mchists.fHmulphi);
1084  mulcalc(mchists.fHmtheta_xz, mchists.fHmctheta_xz, mchists.fHmultheta_xz);
1085  mulcalc(mchists.fHmtheta_yz, mchists.fHmctheta_yz, mchists.fHmultheta_yz);
1086  mulcalc(mchists.fHmmom, mchists.fHmcmom, mchists.fHmulmom);
1087  mulcalc(mchists.fHmlen, mchists.fHmclen, mchists.fHmullen);
1088  }
1089  // Fill efficiency histograms.
1090 
1092  i != fMCHistMap.end(); ++i) {
1093  const MCHists& mchists = i->second;
1094  effcalc(mchists.fHgstartx, mchists.fHmcstartx, mchists.fHestartx);
1095  effcalc(mchists.fHgstarty, mchists.fHmcstarty, mchists.fHestarty);
1096  effcalc(mchists.fHgstartz, mchists.fHmcstartz, mchists.fHestartz);
1097  effcalc(mchists.fHgendx, mchists.fHmcendx, mchists.fHeendx);
1098  effcalc(mchists.fHgendy, mchists.fHmcendy, mchists.fHeendy);
1099  effcalc(mchists.fHgendz, mchists.fHmcendz, mchists.fHeendz);
1100  effcalc(mchists.fHgtheta, mchists.fHmctheta, mchists.fHetheta);
1101  effcalc(mchists.fHgphi, mchists.fHmcphi, mchists.fHephi);
1102  effcalc(mchists.fHgtheta_xz, mchists.fHmctheta_xz, mchists.fHetheta_xz);
1103  effcalc(mchists.fHgtheta_yz, mchists.fHmctheta_yz, mchists.fHetheta_yz);
1104  effcalc(mchists.fHgmom, mchists.fHmcmom, mchists.fHemom);
1105  effcalc(mchists.fHglen, mchists.fHmclen, mchists.fHelen);
1106  }
1107  }
1108 }
geo::Length_t DetHalfWidth(geo::TPCID const &tpcid) const
Returns the half width of the active volume of the specified TPC.
std::string fMCTrackModuleLabel
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
Float_t den
Definition: plot.C:37
void GetPoint(double *Pt, double *Err) const
Definition: Seed.cxx:112
std::string fSeedModuleLabel
STL namespace.
double T() const
Definition: MCStep.h:45
bool isRealData() const
Definition: Event.h:83
TFileDirectory mkdir(std::string const &dir, std::string const &descr="")
virtual double ConvertXToTicks(double X, int p, int t, int c) const =0
double fMatchColinearity
bool isValid() const
Definition: Handle.h:190
geo::Length_t DetHalfHeight(geo::TPCID const &tpcid) const
Returns the half height of the active volume of the specified TPC.
intermediate_table::const_iterator const_iterator
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:42
long seed
Definition: chem4.cc:68
geo::Length_t DetLength(geo::TPCID const &tpcid) const
Returns the length of the active volume of the specified TPC.
EDAnalyzer(Table< Config > const &config)
Definition: EDAnalyzer.h:100
Class def header for mctrack data container.
std::map< int, RecoHists > fRecoHistMap
int PdgCode() const
Definition: MCTrack.h:41
const TLorentzVector & Momentum() const
Definition: MCStep.h:38
SeedAna(fhicl::ParameterSet const &pset)
T * make(ARGS...args) const
std::map< int, MCHists > fMCHistMap
void analyze(const art::Event &evt)
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
double E() const
Definition: MCStep.h:49
const MCStep & Start() const
Definition: MCTrack.h:44
Char_t n[5]
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
unsigned int TrackID() const
Definition: MCTrack.h:42
virtual ~SeedAna()
Float_t w
Definition: plot.C:23
void GetDirection(double *Dir, double *Err) const
Definition: Seed.cxx:102
Definition: fwd.h:25
art framework interface to geometry description
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33