LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
SimulationDrawer.cxx
Go to the documentation of this file.
1 
7 #include <iomanip>
8 #include <algorithm>
9 
10 #include "TParticle.h"
11 #include "TLine.h"
12 #include "TLatex.h"
13 #include "TPolyMarker3D.h"
14 #include "TPolyMarker.h"
15 #include "TPolyLine.h"
16 #include "TPolyLine3D.h"
17 #include "TDatabasePDG.h"
18 
39 
41 
46 
47 namespace {
48  // Utility function to make uniform error messages.
49  void writeErrMsg(const char* fcn,
50  cet::exception const& e)
51  {
52  mf::LogWarning("SimulationDrawer") << "SimulationDrawer::" << fcn
53  << " failed with message:\n"
54  << e;
55  }
56 }
57 
58 namespace evd{
59 
61 {
62  // For now only draw cryostat=0.
64  minx = 1e9;
65  maxx = -1e9;
66  miny = 1e9;
67  maxy = -1e9;
68  minz = 1e9;
69  maxz = -1e9;
70 
71  for(size_t cryoIdx = 0; cryoIdx < geom->Ncryostats(); cryoIdx++)
72  {
73  const geo::CryostatGeo& cryoGeo = geom->Cryostat(cryoIdx);
74 
75  for (size_t tpcIdx = 0; tpcIdx < cryoGeo.NTPC(); tpcIdx++)
76  {
77  const geo::TPCGeo& tpc = cryoGeo.TPC(tpcIdx);
78 
79  std::cout << "Cryo/TPC idx: " << cryoIdx << "/" << tpcIdx << ", TPC center: " << tpc.GetCenter()[0] << ", " << tpc.GetCenter()[1] << ", " << tpc.GetCenter()[2] << std::endl;
80  std::cout << " TPC Active center: " << tpc.GetActiveVolumeCenter()[0] << ", " << tpc.GetActiveVolumeCenter()[1] << ", " << tpc.GetActiveVolumeCenter()[2] << ", H/W/L: " << tpc.ActiveHalfHeight() << "/" << tpc.ActiveHalfWidth() << "/" << tpc.ActiveLength() << std::endl;
81 
82  if (minx>tpc.GetCenter()[0]-tpc.HalfWidth())
83  minx = tpc.GetCenter()[0]-tpc.HalfWidth();
84  if (maxx<tpc.GetCenter()[0]+tpc.HalfWidth())
85  maxx = tpc.GetCenter()[0]+tpc.HalfWidth();
86  if (miny>tpc.GetCenter()[1]-tpc.HalfHeight())
87  miny = tpc.GetCenter()[1]-tpc.HalfHeight();
88  if (maxy<tpc.GetCenter()[1]+tpc.HalfHeight())
89  maxy = tpc.GetCenter()[1]+tpc.HalfHeight();
90  if (minz>tpc.GetCenter()[2]-tpc.Length()/2.)
91  minz = tpc.GetCenter()[2]-tpc.Length()/2.;
92  if (maxz<tpc.GetCenter()[2]+tpc.Length()/2.)
93  maxz = tpc.GetCenter()[2]+tpc.Length()/2.;
94 
95  std::cout << " minx/maxx: " << minx << "/" << maxx << ", miny/maxy: " << miny << "/" << maxy << ", minz/miny: " << minz << "/" << maxz << std::endl;
96  }
97  }
98 }
99 
100  //......................................................................
101 
103  {
104  }
105 
106  //......................................................................
107 
109  evdb::View2D* view)
110  {
111 
112  if( evt.isRealData() ) return;
113 
115  // Skip drawing if option is turned off
116  if (!drawopt->fShowMCTruthText) return;
117 
118  std::vector<const simb::MCTruth*> mctruth;
119  this->GetMCTruth(evt, mctruth);
120 
121  for (unsigned int i=0; i<mctruth.size(); ++i) {
122  std::string mctext;
123  bool firstin = true;
124  bool firstout = true;
125  std::string origin;
126  std::string incoming;
127  std::string outgoing;
128  // Label cosmic rays -- others are pretty obvious
129  if (mctruth[i]->Origin()==simb::kCosmicRay) origin = "c-ray: ";
130  int jmax = TMath::Min(20,mctruth[i]->NParticles());
131  for (int j=0; j<jmax; ++j) {
132  const simb::MCParticle& p = mctruth[i]->GetParticle(j);
133  char buff[1024];
134  if (p.P()>0.05) {
135  sprintf(buff,"#color[%d]{%s #scale[0.75]{[%.1f GeV/c]}}",
138  p.P());
139  }
140  else {
141  sprintf(buff,"#color[%d]{%s}",
144  }
145  if (p.StatusCode()==0) {
146  if (firstin==false) incoming += " + ";
147  incoming += buff;
148  firstin = false;
149  }
150  if (p.StatusCode()==1) {
151  if (firstout==false) outgoing += " + ";
152  outgoing += buff;
153  firstout = false;
154  }
155  } // loop on j particles
156  if (origin=="" && incoming=="") {
157  mctext = outgoing;
158  }
159  else {
160  mctext = origin+incoming+" #rightarrow "+outgoing;
161  }
162  TLatex& latex = view->AddLatex(0.03, 0.2, mctext.c_str());
163  latex.SetTextSize(0.6);
164 
165  } // loop on i mctruth objects
166  }
167 
168  //......................................................................
169 
171  evdb::View2D* /*view*/)
172  {
173  if( evt.isRealData() ) return;
174 
176  // Skip drawing if option is turned off
177  if (!drawopt->fShowMCTruthText) return;
178 
179  std::vector<const simb::MCTruth*> mctruth;
180  this->GetMCTruth(evt, mctruth);
181  std::cout<<"\nMCTruth Ptcl trackID PDG P T Moth Process\n";
182  for (unsigned int i=0; i<mctruth.size(); ++i) {
183  for (int j=0; j<mctruth[i]->NParticles(); ++j) {
184  const simb::MCParticle& p = mctruth[i]->GetParticle(j);
185  if(p.StatusCode() == 0 || p.StatusCode() == 1) {
186  int KE = 1000 * (p.E() - p.Mass());
187  std::cout<<std::right<<std::setw(7)<<i<<std::setw(5)<<j
188  <<std::setw(8)<<p.TrackId()
189  <<" "<<std::setw(14)<<Style::LatexName(p.PdgCode())
190  <<std::setw(7)<<int(1000 * p.P())
191  <<std::setw(7)<<KE<<std::setw(7)<<p.Mother()
192  <<" "<<p.Process()
193  <<"\n";
194  }
195 /*
196  std::cout << Style::LatexName(p.PdgCode())
197  << "\t\t" << p.E() << " GeV"
198  << "\t" << "(" << p.P() << " GeV/c)"
199  << std::endl;
200 */
201  } // loop on j particles in list
202  }
203  std::cout<<"Note: Momentum, P, and kinetic energy, T, in MeV/c\n";
204  } // MCTruthLongText
205 
206 
207  //......................................................................
208  //this is the method you would use to color code hits by the MC truth pdg value
210  evdb::View2D* view,
211  unsigned int plane)
212  {
213  if( evt.isRealData() ) return;
214 
215  const spacecharge::SpaceCharge* sce = lar::providerFrom<spacecharge::SpaceChargeService>();
216 
218  // If the option is turned off, there's nothing to do
219  if (drawopt->fShowMCTruthVectors > 3) {
220  std::cout<<"Unsupported ShowMCTruthVectors option (> 2)\n";
221  return;
222  }
223 
224  detinfo::DetectorProperties const* detprop = lar::providerFrom<detinfo::DetectorPropertiesService>();
225 
228  // get the x position of the plane in question
229  double xyz1[3] = {0.};
230  double xyz2[3] = {0.};
231  // shift the truth by a fixed amount so it doesn't overlay the reco
232  double xShift = -2;
233 
234  static bool first = true;
235  if(first) {
236  std::cout<<"******** Show MCTruth (Genie) particles when ShowMCTruthVectors = 1 or 3 ******** \n";
237  std::cout<<" MCTruth vectors corrected for space charge? "<<sce->EnableCorrSCE()<<" and shifted by "<<xShift<<" cm in X\n";
238  std::cout<<" Neutrons and photons drawn with dotted lines. \n";
239  std::cout<<" Red = e+/-, nue, nuebar. Blue = mu+/-, numu, numubar. Green = tau+/-, nutau, nutaubar.\n";
240  std::cout<<" Yellow = photons. Magenta = pions, protons and nuetrons.\n";
241  std::cout<<"******** Show MCParticle (Geant) decay photons (e.g. from pizeros) when ShowMCTruthVectors = 2 or 3 ******** \n";
242  std::cout<<" Photons > 50 MeV are drawn as dotted lines corrected for space charge and are not shifted.\n";
243  std::cout<<" Decay photon end points are drawn at 2 interaction lengths (44 cm) from the start position.\n";
244  std::cout<<" Color: Green = (50 < E_photon < 100 MeV), Blue = (100 MeV < E_photon < 200 MeV), Red = (E_photon > 300 MeV).\n";
245  }
246 
247  bool showTruth = (drawopt->fShowMCTruthVectors == 1 || drawopt->fShowMCTruthVectors == 3);
248  bool showPhotons = (drawopt->fShowMCTruthVectors > 1);
249 
250  if(showTruth) {
251  // Unpack and draw the MC vectors
252  std::vector<const simb::MCTruth*> mctruth;
253  this->GetMCTruth(evt, mctruth);
254 
255  for (size_t i = 0; i < mctruth.size(); ++i) {
256  if (mctruth[i]->Origin() == simb::kCosmicRay) continue;
257  for (int j = 0; j < mctruth[i]->NParticles(); ++j) {
258  const simb::MCParticle& p = mctruth[i]->GetParticle(j);
259 
260  // Skip all but incoming and out-going particles
261  if (!(p.StatusCode()==0 || p.StatusCode()==1)) continue;
262 
263  double r = p.P()*10.0; // Scale length so 10 cm = 1 GeV/c
264 
265  if (p.StatusCode() == 0) r = -r; // Flip for incoming particles
266 
267  auto gptStart = geo::Point_t(p.Vx(),p.Vy(),p.Vz());
268  geo::Point_t sceOffset {0, 0, 0};
269  if(sce->EnableCorrSCE()) sceOffset = sce->GetPosOffsets(gptStart);
270 // std::cout<<"Pos "<<std::fixed<<std::setprecision(1)<<gptStart.X()<<" "<<gptStart.Y()<<" "<<gptStart.Z();
271 // std::cout<<" sceOffset "<<std::setprecision(1)<<sceOffset.X()<<" "<<sceOffset.Y()<<" "<<sceOffset.Z()<<"\n";
272  xyz1[0] = p.Vx() - sceOffset.X();
273  xyz1[1] = p.Vy() + sceOffset.Y();
274  xyz1[2] = p.Vz() + sceOffset.Z();
275  xyz2[0] = xyz1[0] + r * p.Px()/p.P();
276  xyz2[1] = xyz1[1] + r * p.Py()/p.P();
277  xyz2[2] = xyz1[2] + r * p.Pz()/p.P();
278 
279  double w1 = geo->WireCoordinate(xyz1[1], xyz1[2], (int)plane, rawopt->fTPC, rawopt->fCryostat);
280  double w2 = geo->WireCoordinate(xyz2[1], xyz2[2], (int)plane, rawopt->fTPC, rawopt->fCryostat);
281 
282  double time = detprop->ConvertXToTicks(xyz1[0] + xShift, (int)plane, rawopt->fTPC, rawopt->fCryostat);
283  double time2 = detprop->ConvertXToTicks(xyz2[0] + xShift, (int)plane, rawopt->fTPC, rawopt->fCryostat);
284 
285  if(rawopt->fAxisOrientation < 1){
286  TLine& l = view->AddLine(w1, time, w2, time2);
288  }
289  else{
290  TLine& l = view->AddLine(time, w1, time2, w2);
292  }
293  //
294 
295  } // loop on j particles in list
296  } // loop on truths
297  } // showTruth
298 
299  if(showPhotons) {
300  // draw pizero photons with T > 30 MeV
302  sim::ParticleList const& plist = pi_serv->ParticleList();
303  if(plist.empty()) return;
304  // photon interaction length approximate
305  double r = 44;
306  for(sim::ParticleList::const_iterator ipart = plist.begin(); ipart != plist.end(); ++ipart) {
307  simb::MCParticle* p = (*ipart).second;
308  int trackID = p->TrackId();
309  art::Ptr<simb::MCTruth> theTruth = pi_serv->TrackIdToMCTruth_P(trackID);
310  if(theTruth->Origin() == simb::kCosmicRay) continue;
311  if(p->PdgCode() != 22) continue;
312  if(p->Process() != "Decay") continue;
313  int TMeV = 1000 * (p->E() - p->Mass());
314  if(TMeV < 30) continue;
315  auto gptStart = geo::Point_t(p->Vx(),p->Vy(),p->Vz());
316  geo::Point_t sceOffset {0, 0, 0};
317  if(sce->EnableCorrSCE()) sceOffset = sce->GetPosOffsets(gptStart);
318 // std::cout<<"Pos "<<std::fixed<<std::setprecision(1)<<gptStart.X()<<" "<<gptStart.Y()<<" "<<gptStart.Z();
319 // std::cout<<" sceOffset "<<std::setprecision(1)<<sceOffset.X()<<" "<<sceOffset.Y()<<" "<<sceOffset.Z()<<"\n";
320  xyz1[0] = p->Vx() - sceOffset.X();
321  xyz1[1] = p->Vy() + sceOffset.Y();
322  xyz1[2] = p->Vz() + sceOffset.Z();
323  xyz2[0] = xyz1[0] + r * p->Px()/p->P();
324  xyz2[1] = xyz1[1] + r * p->Py()/p->P();
325  xyz2[2] = xyz1[2] + r * p->Pz()/p->P();
326  double w1 = geo->WireCoordinate(xyz1[1], xyz1[2], (int)plane, rawopt->fTPC, rawopt->fCryostat);
327  double t1 = detprop->ConvertXToTicks(xyz1[0], (int)plane, rawopt->fTPC, rawopt->fCryostat);
328  double w2 = geo->WireCoordinate(xyz2[1], xyz2[2], (int)plane, rawopt->fTPC, rawopt->fCryostat);
329  double t2 = detprop->ConvertXToTicks(xyz2[0], (int)plane, rawopt->fTPC, rawopt->fCryostat);
330  TLine& l = view->AddLine(w1, t1, w2, t2);
331  l.SetLineWidth(2);
332  l.SetLineStyle(kDotted);
333  if(TMeV < 100) {
334  l.SetLineColor(kGreen);
335  } else if(TMeV < 200) {
336  l.SetLineColor(kBlue);
337  } else {
338  l.SetLineColor(kRed);
339  }
340  } // ipart
341  } // showPhotons
342 
343  first = false;
344 
345  } // MCTruthVectors2D
346 
347  //......................................................................
348  //this method draws the true particle trajectories in 3D
350  evdb::View3D* view)
351 {
352  if( evt.isRealData() ) return;
353 
355  // If the option is turned off, there's nothing to do
356  if (!drawopt->fShowMCTruthTrajectories) return;
357 
358  // learn whether we want to draw the scintillation light too;
359  // in fact, we don't care whether it's scintillation or not,
360  // but it is photons with very low energy, close to the optical range
361  bool const fDrawLight = drawopt->fShowScintillationLight;
362 
363  // Space charge service...
364  // const spacecharge::SpaceCharge* sce = lar::providerFrom<spacecharge::SpaceChargeService>();
365 
366  // geo::GeometryCore const* geom = lar::providerFrom<geo::Geometry>();
367  detinfo::DetectorProperties const* theDetector = lar::providerFrom<detinfo::DetectorPropertiesService>();
368  detinfo::DetectorClocks const* detClocks = lar::providerFrom<detinfo::DetectorClocksService>();
370 
371  // get the particles from the Geant4 step
372  std::vector<const simb::MCParticle*> plist;
373  this->GetParticle(evt, plist);
374 
375  // Useful variables
376  double xMinimum(-1.*(maxx-minx));
377  double xMaximum( 2.*(maxx-minx));
378 
379  double xMinFromTicks = theDetector->ConvertTicksToX(0,0,0,0);
380  double xMaxFromTicks = theDetector->ConvertTicksToX(theDetector->NumberTimeSamples(),0,0,0);
381 
382  std::cout << "# samples: " << theDetector->NumberTimeSamples() << ", min/max X: " << xMinFromTicks << "/" << xMaxFromTicks << ", xMinimum/xMaximum: " << xMinimum << "/" << xMaximum << std::endl;
383 
384  // Define a couple of colors for neutrals and if we gray it out...
385  Color_t const scintillationColor = kMagenta;
386  int neutralColor(12);
387  int grayedColor(15);
388  int neutrinoColor(38);
389 
390  // Use the LArVoxelList to get the true energy deposition locations as opposed to using MCTrajectories
392 
393  mf::LogDebug("SimulationDrawer") << "Starting loop over " << plist.size() << " McParticles, voxel list size is " << voxels.size() << std::endl;
394 
395  // Using the voxel information can be slow (see previous implementation of this code).
396  // In order to speed things up we have modified the strategy:
397  // 1) Make one pass through the list of voxels
398  // 2) For each voxel, keep track of the MCParticle contributing energy to it and it's position
399  // which is done by keeping a map between the MCParticle and a vector of positions
400  // 3) Then loop through the map to draw the particle trajectories.
401  // One caveat is the need for MCParticles... and the voxels contain the track ids. So we'll need one
402  // more loop to make a map of track id's and MCParticles.
403 
404  // First up is to build the map between track id's and associated MCParticles so we can recover when looping over voxels
405  std::map<int, const simb::MCParticle*> trackToMcParticleMap;
406 
407  // Should we display the trajectories too?
408  constexpr unsigned int MaxParticles = 100000000;
409  double minPartEnergy(0.01);
410 
411  auto const* pDatabasePDG = TDatabasePDG::Instance();
412 
413  unsigned int nDrawnParticles = 0U;
414  for (const simb::MCParticle* mcPart: plist) {
415  trackToMcParticleMap[mcPart->TrackId()] = mcPart;
416 
417  // Quick loop through to draw trajectories...
418  if (!drawopt->fShowMCTruthTrajectories) continue;
419 
420  // Is there an associated McTrajectory?
421  const simb::MCTrajectory& mcTraj = mcPart->Trajectory();
422  if (mcTraj.empty()) continue;
423 
424  int const pdgCode(mcPart->PdgCode());
425  int const colorIdx
426  { drawopt->fShowMCTruthColors? evd::Style::ColorFromPDG(mcPart->PdgCode()): grayedColor };
427  TParticlePDG const* partPDG(pDatabasePDG->GetParticle(pdgCode));
428  double const partCharge = partPDG ? partPDG->Charge() : 0.;
429  double const partEnergy = mcPart->E();
430 
431  // is this a photon with less than 100 eV of energy?
432  // (LArG4 scintillation photons are "Rootini", PDG code 0... *burp*)
433  bool const isScintillationLight = ((pdgCode == 22) || (pdgCode == 0)) && (partEnergy < 1e-7);
434 
435  if (isScintillationLight) {
436  // we do not apply any threshold, but we draw it only if requested
437  if (!fDrawLight) continue;
438  }
439  else { // apply the "normal" threshold
440  if (partEnergy < minPartEnergy) continue;
441  }
442 
443  if (nDrawnParticles++ >= MaxParticles) {
444  if (nDrawnParticles == MaxParticles) {
445  mf::LogWarning("SimulationDrawer")
446  << "Only " << nDrawnParticles << "/" << plist.size()
447  << " MCParticle's will be displayed.";
448  }
449  continue; // too many!
450  }
451 
452  /*
453  * The following is meant to get the correct offset for drawing the particle trajectory
454  * In particular, the cosmic rays will not be correctly placed without this
455  *
456  * More specifically, the true location of the cosmic ray betrays the
457  * expectation of the reader.
458  * When we look at an event, we expect that if two particles are close
459  * by, their observables (in our case, ionization tracks) will be as
460  * close. The event display projects into a static picture everything
461  * that happens at any time. This is not a big deal in a fast detector,
462  * where the time window can be short, but has consequences of mixing
463  * activity at different times for a LArTPC.
464  * The slowness of TPCs is a major problem for physics. Here we are
465  * facing a minor spin-off of that problem: if a pion is produced at a
466  * certain position x by the neutrino interaction, and then one
467  * millisecond later a cosmic rays passes at the same location, the
468  * display will show both at the same position x, but the detection
469  * will be delayed by the number of ticks the TDC counted in that one
470  * millisecond. Reconstruction will not be fooled by the close distance
471  * of the two tracks, but the display leads us to expect that confusion
472  * /should/ arise.
473  *
474  */
475  //double g4Ticks(detClocks->TPCG4Time2Tick(mcPart->T())+theDetector->GetXTicksOffset(0,0,0)-theDetector->TriggerOffset());
476  //double g4Ticks(detClocks->TPCG4Time2Tick(mcPart->T())+theDetector->GetXTicksOffset(0,0,0));
477  double g4Ticks(detClocks->TPCG4Time2Tick(mcPart->T()));
478  //double g4Ticks(detClocks->TPCG4Time2Tick(mcPart->T()));
479  double xOffset(0.); //(theDetector->ConvertTicksToX(g4Ticks, 0, 0, 0));
480  bool xOffsetNotSet(true);
481  // collect the points from this particle
482  int const numTrajPoints = mcTraj.size();
483 
484  std::vector<double> hitPositions;
485  hitPositions.reserve(3*numTrajPoints);
486  std::size_t hitCount = 0U;
487 
488 
489  for(int hitIdx = 0; hitIdx < numTrajPoints; hitIdx++)
490  {
491  double xPos = mcTraj.X(hitIdx);
492  double yPos = mcTraj.Y(hitIdx);
493  double zPos = mcTraj.Z(hitIdx);
494 
495  // If the original simulated hit did not occur in the TPC volume then don't draw it
496  if (xPos < minx || xPos > maxx || yPos < miny || yPos > maxy|| zPos < minz || zPos > maxz) continue;
497 
498  // Check xOffset state and set if necessary
499  if (xOffsetNotSet)
500  {
501  try
502  {
503  auto const* pTPC = geom->PositionToTPCptr(geo::Point_t(xPos, yPos, zPos));
504  if (!pTPC) continue;
505 
506  geo::PlaneID const firstPlane { pTPC->ID(), 0 };
507  xMinFromTicks = theDetector->ConvertTicksToX(0, firstPlane);
508  xMaxFromTicks = theDetector->ConvertTicksToX(theDetector->NumberTimeSamples(), firstPlane);
509 
510  if (xMaxFromTicks < xMinFromTicks) std::swap(xMinFromTicks,xMaxFromTicks);
511 
512  xOffset = xMinFromTicks - theDetector->ConvertTicksToX(g4Ticks, firstPlane);
513  xOffsetNotSet = false;
514  xOffset = 0.; // ?!?
515  }
516  catch(...) {continue;}
517  }
518 
519  // Now move the hit position to correspond to the timing
520  xPos += xOffset;
521 
522  // Check fiducial limits
523  if (xPos > xMinFromTicks && xPos < xMaxFromTicks)
524  {
525  // Check for space charge offsets
526 // if (spaceCharge->EnableSimEfieldSCE())
527 // {
528 // std::vector<double> offsetVec = spaceCharge->GetPosOffsets(xPos,yPos,zPos);
529 // xPos += offsetVec[0] - 0.7;
530 // yPos -= offsetVec[1];
531 // zPos -= offsetVec[2];
532 // }
533 
534  hitPositions.push_back(xPos);
535  hitPositions.push_back(yPos);
536  hitPositions.push_back(zPos);
537  ++hitCount;
538  }
539  } // for hitIdx
540 
541 
542  TPolyLine3D& pl(view->AddPolyLine3D(1, colorIdx, 1, 1));
543 
544  // Draw neutrals as a gray dotted line to help fade into background a bit...
545  if (isScintillationLight) {
546  pl.SetLineColor(scintillationColor);
547  pl.SetLineStyle(kSolid);
548  pl.SetLineWidth(1);
549  }
550  else if (partCharge == 0.)
551  {
552  pl.SetLineColor(neutralColor);
553  pl.SetLineStyle(kDotted);
554  pl.SetLineWidth(1);
555  }
556  pl.SetPolyLine(hitCount, hitPositions.data(), "");
557  } // for mcPart
558 
559 
560  // Now we set up and build the map between MCParticles and a vector of positions obtained from the voxels
561  std::map<const simb::MCParticle*, std::vector<std::vector<double> > > partToPosMap;
562 
564  for(vxitr = voxels.begin(); vxitr != voxels.end(); vxitr++)
565  {
566  const sim::LArVoxelData &vxd = (*vxitr).second;
567 
568  for(size_t partIdx = 0; partIdx < vxd.NumberParticles(); partIdx++)
569  {
570  if(vxd.Energy(partIdx) > drawopt->fMinEnergyDeposition)
571  {
572  int trackId = vxd.TrackID(partIdx);
573 
574  // It can be in some instances that mcPart here could be zero.
575  const simb::MCParticle* mcPart = trackToMcParticleMap[trackId];
576 
577  partToPosMap[mcPart].push_back(std::vector<double>(3));
578 
579  partToPosMap[mcPart].back()[0] = vxd.VoxelID().X();
580  partToPosMap[mcPart].back()[1] = vxd.VoxelID().Y();
581  partToPosMap[mcPart].back()[2] = vxd.VoxelID().Z();
582  }
583  } // end if this track id is in the current voxel
584  }// end loop over voxels
585 
586  // Finally ready for the main event! Simply loop through the map between MCParticle and positions to
587  // draw the trajectories
588  std::map<const simb::MCParticle*, std::vector<std::vector<double> > >::iterator partToPosMapItr;
589 
590  for(partToPosMapItr = partToPosMap.begin(); partToPosMapItr != partToPosMap.end(); partToPosMapItr++)
591  {
592  // Recover the McParticle, we'll need to access several data members so may as well dereference it
593  const simb::MCParticle* mcPart = partToPosMapItr->first;
594 
595  // Apparently, it can happen that we get a null pointer here or maybe no points to plot
596  if (!mcPart || partToPosMapItr->second.empty()) continue;
597 
598  // The following is meant to get the correct offset for drawing the particle trajectory
599  // In particular, the cosmic rays will not be correctly placed without this
600  //double g4Ticks(detClocks->TPCG4Time2Tick(mcPart->T())+theDetector->GetXTicksOffset(0,0,0)-theDetector->TriggerOffset());
601  //double g4Ticks(detClocks->TPCG4Time2Tick(mcPart->T())+theDetector->GetXTicksOffset(0,0,0));
602  double g4Ticks(detClocks->TPCG4Time2Tick(mcPart->T()));
603 // double g4Ticks(detClocks->TPCG4Time2Tick(mcPart->T()));
604  double xOffset(0.); //theDetector->ConvertTicksToX(g4Ticks, 0, 0, 0));
605  bool xOffsetNotSet(true);
606 
607  int colorIdx(evd::Style::ColorFromPDG(mcPart->PdgCode()));
608  int markerIdx(kFullDotSmall);
609  int markerSize(2);
610 
611  if (!drawopt->fShowMCTruthFullSize)
612  {
613  colorIdx = grayedColor;
614  markerIdx = kDot;
615  markerSize = 1;
616  }
617 
618  std::unique_ptr<double[]> hitPositions(new double[3*partToPosMapItr->second.size()]);
619  int hitCount(0);
620 
621  // Now loop over points and add to trajectory
622  for(size_t posIdx = 0; posIdx < partToPosMapItr->second.size(); posIdx++)
623  {
624  const std::vector<double>& posVec = partToPosMapItr->second[posIdx];
625 
626  // Check xOffset state and set if necessary
627  if (xOffsetNotSet)
628  {
629  double hitLocation[] = {posVec[0],posVec[1],posVec[2]};
630 
631  try
632  {
633  const geo::CryostatGeo& cryoGeo = geom->PositionToCryostat(hitLocation);
634  int tpcIdx = cryoGeo.FindTPCAtPosition(hitLocation, 1.);
635 
636  xMinFromTicks = theDetector->ConvertTicksToX(0,0,tpcIdx,cryoGeo.ID().Cryostat);
637  xMaxFromTicks = theDetector->ConvertTicksToX(theDetector->NumberTimeSamples(),0,tpcIdx,cryoGeo.ID().Cryostat);
638 
639  if (xMaxFromTicks < xMinFromTicks) std::swap(xMinFromTicks,xMaxFromTicks);
640 
641  xOffset = xMinFromTicks - theDetector->ConvertTicksToX(g4Ticks, 0, tpcIdx, cryoGeo.ID().Cryostat);
642  xOffsetNotSet = false;
643  xOffset = 0.;
644  }
645  catch(...) {continue;}
646  }
647 
648  double xCoord = posVec[0] + xOffset;
649 
650  if (xCoord > xMinFromTicks && xCoord < xMaxFromTicks)
651  {
652  hitPositions[3*hitCount ] = xCoord;
653  hitPositions[3*hitCount + 1] = posVec[1];
654  hitPositions[3*hitCount + 2] = posVec[2];
655  hitCount++;
656  }
657  }
658 
659  TPolyMarker3D& pm = view->AddPolyMarker3D(1, colorIdx, markerIdx, markerSize);
660  pm.SetPolyMarker(hitCount, hitPositions.get(), markerIdx);
661  }
662 
663  // Finally, let's see if we can draw the incoming particle from the MCTruth information
664  std::vector<const simb::MCTruth*> mctruth;
665  this->GetMCTruth(evt, mctruth);
666 
667  // Loop through the MCTruth vector
668  for (unsigned int idx = 0; idx < mctruth.size(); idx++)
669  {
670  // Go through each MCTruth object in the list
671  for (int particleIdx = 0; particleIdx < mctruth[idx]->NParticles(); particleIdx++)
672  {
673  const simb::MCParticle& mcPart = mctruth[idx]->GetParticle(particleIdx);
674 
675  // A negative mother id indicates the "primary" particle
676  if(mcPart.Mother() == -1 && mcPart.StatusCode() == 0)
677  {
678  mf::LogDebug("SimulationDrawer") << mcPart << std::endl;
679 
680  // Get position vector
681  TVector3 particlePosition(mcPart.Vx(),mcPart.Vy(),mcPart.Vz());
682 
683  // Get direction vector (in opposite direction)
684  TVector3 oppPartDir(-mcPart.Px(),-mcPart.Py(),-mcPart.Pz());
685 
686  if (oppPartDir.Mag2() > 0.) oppPartDir.SetMag(1.);
687 
688  double arcLenToDraw = -particlePosition.Z() / oppPartDir.CosTheta();
689 
690  // No point in drawing if arc length is zero (e.g. Ar nucleus)
691  if (arcLenToDraw > 0.)
692  {
693  // Draw the line, use an off color to be unique
694  TPolyLine3D& pl(view->AddPolyLine3D(2, neutrinoColor, 1, 2));
695 
696  pl.SetPoint(0,particlePosition.X(),particlePosition.Y(),particlePosition.Z());
697 
698  particlePosition += std::min(arcLenToDraw + 10.,1000.) * oppPartDir;
699 
700  pl.SetPoint(1,particlePosition.X(),particlePosition.Y(),particlePosition.Z());
701  }
702  }
703  // The particles we want to draw will be early in the list so break out if we didn't find them
704  else break;
705  } // loop on particles in list
706  }
707 
708  return;
709 }
710 
711  //......................................................................
712  //this method draws the true particle trajectories in 3D Ortho view.
715  double msize,
716  evdb::View2D* view)
717  {
718  if( evt.isRealData() ) return;
719 
721 
722  // If the option is turned off, there's nothing to do
723  if (!drawopt->fShowMCTruthTrajectories) return;
724 
725  geo::GeometryCore const* geom = lar::providerFrom<geo::Geometry>();
726  detinfo::DetectorProperties const* theDetector = lar::providerFrom<detinfo::DetectorPropertiesService>();
727  detinfo::DetectorClocks const* detClocks = lar::providerFrom<detinfo::DetectorClocksService>();
728 
729  // get the particles from the Geant4 step
730  std::vector<const simb::MCParticle*> plist;
731  this->GetParticle(evt, plist);
732 
733  // Useful variables
734 
735  //double detHalfWidth(geom->DetHalfWidth());
736  double xMinimum(-1.*(maxx-minx));
737  double xMaximum( 2.*(maxx-minx));
738 
739 // double detHalfHeight(geom->DetHalfHeight());
740 // double zMinimum(0.);
741 // double zMaximum(geom->DetLength());
742 
743  // Use the LArVoxelList to get the true energy deposition locations as opposed to using MCTrajectories
745 
746  mf::LogDebug("SimulationDrawer") << "Starting loop over " << plist.size() << " McParticles, voxel list size is " << voxels.size() << std::endl;
747 
748  // Using the voxel information can be slow (see previous implementation of this code).
749  // In order to speed things up we have modified the strategy:
750  // 1) Make one pass through the list of voxels
751  // 2) For each voxel, keep track of the MCParticle contributing energy to it and it's position
752  // which is done by keeping a map between the MCParticle and a vector of positions
753  // 3) Then loop through the map to draw the particle trajectories.
754  // One caveat is the need for MCParticles... and the voxels contain the track ids. So we'll need one
755  // more loop to make a map of track id's and MCParticles.
756 
757  // First up is to build the map between track id's and associated MCParticles so we can recover when looping over voxels
758  std::map<int, const simb::MCParticle*> trackToMcParticleMap;
759 
760  // Should we display the trajectories too?
761  bool displayMcTrajectories(true);
762  double minPartEnergy(0.025);
763 
764  double tpcminx = 1.0; double tpcmaxx = -1.0;
765  double xOffset = 0.0; double g4Ticks = 0.0;
766  double coeff = 0.0; double readoutwindowsize = 0.0;
767  double vtx[3] = {0.0, 0.0, 0.0};
768  for(size_t p = 0; p < plist.size(); ++p)
769  {
770  trackToMcParticleMap[plist[p]->TrackId()] = plist[p];
771 
772  // Quick loop through to drawn trajectories...
773  if (displayMcTrajectories)
774  {
775  // Is there an associated McTrajectory?
776  const simb::MCParticle* mcPart = plist[p];
777  const simb::MCTrajectory& mcTraj = mcPart->Trajectory();
778 
779  int pdgCode(mcPart->PdgCode());
780  TParticlePDG* partPDG(TDatabasePDG::Instance()->GetParticle(pdgCode));
781  double partCharge = partPDG ? partPDG->Charge() : 0.;
782  double partEnergy = mcPart->E();
783 
784  if (!mcTraj.empty() && partEnergy > minPartEnergy && mcPart->TrackId() < 100000000)
785  {
786  // collect the points from this particle
787  int numTrajPoints = mcTraj.size();
788 
789  std::unique_ptr<double[]> hitPosX(new double[numTrajPoints]);
790  std::unique_ptr<double[]> hitPosY(new double[numTrajPoints]);
791  std::unique_ptr<double[]> hitPosZ(new double[numTrajPoints]);
792  int hitCount(0);
793 
794  double xPos = mcTraj.X(0);
795  double yPos = mcTraj.Y(0);
796  double zPos = mcTraj.Z(0);
797 
798  tpcminx = 1.0; tpcmaxx = -1.0;
799  xOffset = 0.0; g4Ticks = 0.0;
800  vtx[0] = 0.0; vtx[1] = 0.0; vtx[2] = 0.0;
801  coeff = 0.0; readoutwindowsize = 0.0;
802  for(int hitIdx = 0; hitIdx < numTrajPoints; hitIdx++)
803  {
804  xPos = mcTraj.X(hitIdx);
805  yPos = mcTraj.Y(hitIdx);
806  zPos = mcTraj.Z(hitIdx);
807 
808  // If the original simulated hit did not occur in the TPC volume then don't draw it
809  if (xPos < minx || xPos > maxx || yPos < miny || yPos > maxy|| zPos < minz || zPos > maxz) continue;
810 
811  if ((xPos < tpcminx) || (xPos > tpcmaxx))
812  {
813  vtx[0] = xPos; vtx[1] = yPos; vtx[2] = zPos;
814  geo::TPCID tpcid = geom->FindTPCAtPosition(vtx);
815  unsigned int cryo = geom->FindCryostatAtPosition(vtx);
816 
817  if (tpcid.isValid)
818  {
819  unsigned int tpc = tpcid.TPC;
820  const geo::TPCGeo& tpcgeo = geom->GetElement(tpcid);
821  tpcminx = tpcgeo.MinX(); tpcmaxx = tpcgeo.MaxX();
822 
823  coeff = theDetector->GetXTicksCoefficient(tpc, cryo);
824  readoutwindowsize = theDetector->ConvertTicksToX(theDetector->ReadOutWindowSize(), 0, tpc, cryo);
825 
826  // The following is meant to get the correct offset for drawing the particle trajectory
827  // In particular, the cosmic rays will not be correctly placed without this
828  g4Ticks = detClocks->TPCG4Time2Tick(mcPart->T())
829  +theDetector->GetXTicksOffset(0, tpc, cryo)
830  -theDetector->TriggerOffset();
831 
832  xOffset = theDetector->ConvertTicksToX(g4Ticks, 0, tpc, cryo);
833  }
834  else { xOffset = 0; tpcminx = 1.0; tpcmaxx = -1.0; coeff = 0.0; readoutwindowsize = 0.0;}
835  }
836 
837  // Now move the hit position to correspond to the timing
838  xPos += xOffset;
839 
840  bool inreadoutwindow = false;
841  if (coeff < 0)
842  {
843  if ((xPos > readoutwindowsize) && (xPos < tpcmaxx)) inreadoutwindow = true;
844  }
845  else if (coeff > 0)
846  {
847  if ((xPos > tpcminx) && (xPos < readoutwindowsize)) inreadoutwindow = true;
848  }
849 
850  if (!inreadoutwindow) continue;
851 
852  // Check fiducial limits
853  if (xPos > xMinimum && xPos < xMaximum)
854  {
855  hitPosX[hitCount] = xPos;
856  hitPosY[hitCount] = yPos;
857  hitPosZ[hitCount] = zPos;
858  hitCount++;
859  }
860 
861  }
862 
863  TPolyLine& pl = view->AddPolyLine(1, evd::Style::ColorFromPDG(mcPart->PdgCode()), 1, 1); //kFullCircle, msize);
864 
865  // Draw neutrals as a gray dotted line to help fade into background a bit...
866  if (partCharge == 0.)
867  {
868  pl.SetLineColor(13);
869  pl.SetLineStyle(3);
870  pl.SetLineWidth(1);
871  }
872 
873  if(proj == evd::kXY)
874  pl.SetPolyLine(hitCount, hitPosX.get(), hitPosY.get(), "");
875  else if(proj == evd::kXZ)
876  pl.SetPolyLine(hitCount, hitPosZ.get(), hitPosX.get(), "");
877  else if(proj == evd::kYZ)
878  pl.SetPolyLine(hitCount, hitPosZ.get(), hitPosY.get(), "");
879  }
880  }
881  }
882 
883  // Now we set up and build the map between MCParticles and a vector of positions obtained from the voxels
884  std::map<const simb::MCParticle*, std::vector<std::vector<double> > > partToPosMap;
885 
887  for(vxitr = voxels.begin(); vxitr != voxels.end(); vxitr++)
888  {
889  const sim::LArVoxelData &vxd = (*vxitr).second;
890 
891  for(size_t partIdx = 0; partIdx < vxd.NumberParticles(); partIdx++)
892  {
893  if(vxd.Energy(partIdx) > drawopt->fMinEnergyDeposition)
894  {
895  int trackId = vxd.TrackID(partIdx);
896 
897  // It can be in some instances that mcPart here could be zero.
898  const simb::MCParticle* mcPart = trackToMcParticleMap[trackId];
899 
900  partToPosMap[mcPart].push_back(std::vector<double>(3));
901 
902  partToPosMap[mcPart].back()[0] = vxd.VoxelID().X();
903  partToPosMap[mcPart].back()[1] = vxd.VoxelID().Y();
904  partToPosMap[mcPart].back()[2] = vxd.VoxelID().Z();
905  }
906  } // end if this track id is in the current voxel
907  }// end loop over voxels
908 
909  // Finally ready for the main event! Simply loop through the map between MCParticle and positions to
910  // draw the trajectories
911  std::map<const simb::MCParticle*, std::vector<std::vector<double> > >::iterator partToPosMapItr;
912 
913  for(partToPosMapItr = partToPosMap.begin(); partToPosMapItr != partToPosMap.end(); partToPosMapItr++)
914  {
915  // Recover the McParticle, we'll need to access several data members so may as well dereference it
916  const simb::MCParticle* mcPart = partToPosMapItr->first;
917 
918  // Apparently, it can happen that we get a null pointer here or maybe no points to plot
919  if (!mcPart || partToPosMapItr->second.empty()) continue;
920 
921  tpcminx = 1.0; tpcmaxx = -1.0;
922  xOffset = 0.0; g4Ticks = 0.0;
923  std::vector< std::array<double, 3> > posVecCorr;
924  posVecCorr.reserve(partToPosMapItr->second.size());
925  coeff = 0.0; readoutwindowsize = 0.0;
926 
927  // Now loop over points and add to trajectory
928  for(size_t posIdx = 0; posIdx < partToPosMapItr->second.size(); posIdx++)
929  {
930  const std::vector<double>& posVec = partToPosMapItr->second[posIdx];
931 
932  if ((posVec[0] < tpcminx) || (posVec[0] > tpcmaxx))
933  {
934  vtx[0] = posVec[0]; vtx[1] = posVec[1]; vtx[2] = posVec[2];
935  geo::TPCID tpcid = geom->FindTPCAtPosition(vtx);
936  unsigned int cryo = geom->FindCryostatAtPosition(vtx);
937 
938  if (tpcid.isValid)
939  {
940  unsigned int tpc = tpcid.TPC;
941 
942  const geo::TPCGeo& tpcgeo = geom->GetElement(tpcid);
943  tpcminx = tpcgeo.MinX(); tpcmaxx = tpcgeo.MaxX();
944 
945  coeff = theDetector->GetXTicksCoefficient(tpc, cryo);
946  readoutwindowsize = theDetector->ConvertTicksToX(theDetector->ReadOutWindowSize(), 0, tpc, cryo);
947  // The following is meant to get the correct offset for drawing the particle trajectory
948  // In particular, the cosmic rays will not be correctly placed without this
949  g4Ticks = detClocks->TPCG4Time2Tick(mcPart->T())
950  +theDetector->GetXTicksOffset(0, tpc, cryo)
951  -theDetector->TriggerOffset();
952 
953  xOffset = theDetector->ConvertTicksToX(g4Ticks, 0, tpc, cryo);
954  }
955  else { xOffset = 0; tpcminx = 1.0; tpcmaxx = -1.0; coeff = 0.0; readoutwindowsize = 0.0; }
956  }
957 
958  double xCoord = posVec[0] + xOffset;
959 
960  bool inreadoutwindow = false;
961  if (coeff < 0)
962  {
963  if ((xCoord > readoutwindowsize) && (xCoord < tpcmaxx)) inreadoutwindow = true;
964  }
965  else if (coeff > 0)
966  {
967  if ((xCoord > tpcminx) && (xCoord < readoutwindowsize)) inreadoutwindow = true;
968  }
969 
970  if (inreadoutwindow && (xCoord > xMinimum && xCoord < xMaximum))
971  {
972  posVecCorr.push_back({{xCoord, posVec[1], posVec[2] }});
973  }
974  }
975 
976  TPolyMarker& pm = view->AddPolyMarker(posVecCorr.size(), evd::Style::ColorFromPDG(mcPart->PdgCode()), kFullDotMedium, 2); //kFullCircle, msize);
977 
978  for (size_t p = 0; p < posVecCorr.size(); ++p)
979  {
980  if(proj == evd::kXY)
981  pm.SetPoint(p, posVecCorr[p][0], posVecCorr[p][1]);
982  else if(proj == evd::kXZ)
983  pm.SetPoint(p, posVecCorr[p][2], posVecCorr[p][0]);
984  else if(proj == evd::kYZ)
985  pm.SetPoint(p, posVecCorr[p][2], posVecCorr[p][1]);
986  }
987  }
988 
989  return;
990  }
991 
992  //......................................................................
994  std::vector<const simb::MCParticle*>& plist)
995  {
996  plist.clear();
997 
998  if( evt.isRealData() ) return 0;
999 
1001 
1002  std::vector<const simb::MCParticle*> temp;
1003 
1005  // use get by Type because there should only be one collection of these in the event
1006  try{
1007  evt.getView(drawopt->fG4ModuleLabel, plcol);
1008  for(unsigned int i = 0; i < plcol.vals().size(); ++i){
1009  temp.push_back(plcol.vals().at(i));
1010  }
1011  temp.swap(plist);
1012  }
1013  catch(cet::exception& e){
1014  writeErrMsg("GetRawDigits", e);
1015  }
1016 
1017  return plist.size();
1018 
1019  }
1020 
1021  //......................................................................
1022 
1024  std::vector<const simb::MCTruth*>& mcvec)
1025  {
1026  mcvec.clear();
1027 
1028  if( evt.isRealData() ) return 0;
1029 
1030  std::vector<const simb::MCTruth*> temp;
1031 
1032  std::vector< art::Handle< std::vector<simb::MCTruth> > > mctcol;
1033  // use get by Type because there should only be one collection of these in the event
1034  try{
1035  evt.getManyByType(mctcol);
1036  for(size_t mctc = 0; mctc < mctcol.size(); ++mctc){
1037  art::Handle< std::vector<simb::MCTruth> > mclistHandle = mctcol[mctc];
1038 
1039  for(size_t i = 0; i < mclistHandle->size(); ++i){
1040  temp.push_back(&(mclistHandle->at(i)));
1041  }
1042  }
1043  temp.swap(mcvec);
1044  }
1045  catch(cet::exception& e){
1046  writeErrMsg("GetMCTruth", e);
1047  }
1048 
1049  return mcvec.size();
1050  }
1051 
1052 
1053  //......................................................................
1054 
1055  void SimulationDrawer::HiLite(int trkId, bool dohilite)
1056  {
1057  fHighlite[trkId] = dohilite;
1058  }
1059 
1060 }// namespace
double E(const int i=0) const
Definition: MCParticle.h:237
double Z(const size_type i) const
Definition: MCTrajectory.h:154
double X(const size_type i) const
Definition: MCTrajectory.h:152
int PdgCode() const
Definition: MCParticle.h:216
bool empty() const
Definition: ParticleList.h:314
Point GetActiveVolumeCenter() const
Returns the center of the TPC active volume in world coordinates [cm].
Definition: TPCGeo.h:247
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:112
double Py(const int i=0) const
Definition: MCParticle.h:235
Utilities related to art service access.
void MCTruthLongText(const art::Event &evt, evdb::View2D *view)
CryostatGeo const & GetElement(geo::CryostatID const &cryoid) const
Returns the specified cryostat.
unsigned int fTPC
TPC number to draw, typically set by TWQProjectionView.
TTree * t1
Definition: plottest35.C:26
void HiLite(int trkId, bool hlt=true)
TPolyLine & AddPolyLine(int n, int c, int w, int s)
Definition: View2D.cxx:210
std::string fG4ModuleLabel
module label producing sim::SimChannel objects
size_type size() const
Definition: LArVoxelList.h:140
Container of LAr voxel information.
double ActiveHalfHeight() const
Half height (associated with y coordinate) of active TPC volume [cm].
Definition: TPCGeo.h:91
const simb::MCTrajectory & Trajectory() const
Definition: MCParticle.h:257
int Mother() const
Definition: MCParticle.h:217
TLine & AddLine(double x1, double y1, double x2, double y2)
Definition: View2D.cxx:187
list_type::const_iterator const_iterator
Definition: ParticleList.h:132
simb::Origin_t Origin() const
Definition: MCTruth.h:71
double Mass() const
Definition: MCParticle.h:243
double MinX() const
Returns the world x coordinate of the start of the box.
Definition: BoxBoundedGeo.h:90
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
bool isValid
Whether this ID points to a valid element.
Definition: geo_types.h:129
Geometry information for a single TPC.
Definition: TPCGeo.h:37
double Px(const int i=0) const
Definition: MCParticle.h:234
static sim::LArVoxelList GetLArVoxelList(const art::Event &evt, std::string moduleLabel)
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:130
int GetMCTruth(const art::Event &evt, std::vector< const simb::MCTruth * > &mctruth)
int StatusCode() const
Definition: MCParticle.h:215
double MaxX() const
Returns the world x coordinate of the end of the box.
Definition: BoxBoundedGeo.h:93
A collection of drawable 2-D objects.
static void FromPDG(TLine &line, int pdgcode)
Definition: Style.cxx:139
bool isRealData() const
Definition: Event.h:83
Geometry information for a single cryostat.
Definition: CryostatGeo.h:36
OrthoProj_t
Definition: OrthoProj.h:12
unsigned int Ncryostats() const
Returns the number of cryostats in the detector.
std::string Process() const
Definition: MCParticle.h:219
void MCTruth3D(const art::Event &evt, evdb::View3D *view)
Particle class.
bool empty() const
Definition: MCTrajectory.h:170
iterator begin()
Definition: LArVoxelList.h:131
int TrackId() const
Definition: MCParticle.h:214
virtual double ConvertXToTicks(double X, int p, int t, int c) const =0
double Length() const
Length is associated with z coordinate [cm].
Definition: TPCGeo.h:107
list_type::const_iterator const_iterator
Definition: LArVoxelList.h:79
virtual bool EnableCorrSCE() const =0
geo::TPCID FindTPCAtPosition(double const worldLoc[3]) const
Returns the ID of the TPC at specified location.
TPolyLine3D & AddPolyLine3D(int n, int c, int w, int s)
Definition: View3D.cxx:105
std::size_t getView(std::string const &moduleLabel, std::string const &productInstanceName, std::vector< ELEMENT const * > &result) const
Definition: DataViewImpl.h:474
virtual geo::Vector_t GetPosOffsets(geo::Point_t const &point) const =0
double Y(const size_type i) const
Definition: MCTrajectory.h:153
Encapsulates the information we want store for a voxel.
LArSoft includes.
unsigned int fCryostat
Cryostat number to draw, typically set by TWQProjectionView.
double Y() const
Definition: LArVoxelID.cxx:79
double ActiveHalfWidth() const
Half width (associated with x coordinate) of active TPC volume [cm].
Definition: TPCGeo.h:87
int GetParticle(const art::Event &evt, std::vector< const simb::MCParticle * > &plist)
double P(const int i=0) const
Definition: MCParticle.h:238
TPolyMarker & AddPolyMarker(int n, int c, int st, double sz)
Definition: View2D.cxx:157
static int ColorFromPDG(int pdgcode)
Definition: Style.cxx:65
double T(const int i=0) const
Definition: MCParticle.h:228
iterator begin()
Definition: ParticleList.h:305
void getManyByType(std::vector< Handle< PROD >> &results) const
Definition: DataViewImpl.h:446
unsigned int NTPC() const
Number of TPCs in this cryostat.
Definition: CryostatGeo.h:155
size_type NumberParticles() const
Definition: LArVoxelData.h:202
CryostatGeo const & Cryostat(geo::CryostatID const &cryoid) const
Returns the specified cryostat.
Definition: fwd.h:47
virtual unsigned int NumberTimeSamples() const =0
The data type to uniquely identify a TPC.
Definition: geo_types.h:195
Description of geometry of one entire detector.
TLatex & AddLatex(double x, double y, const char *text)
Definition: View2D.cxx:308
double ActiveLength() const
Length (associated with z coordinate) of active TPC volume [cm].
Definition: TPCGeo.h:95
double Z() const
Definition: LArVoxelID.cxx:86
bool fShowScintillationLight
Whether to draw low energy light (default: no).
void MCTruthShortText(const art::Event &evt, evdb::View2D *view)
Conversion of times between different formats and references.
TTree * t2
Definition: plottest35.C:36
double HalfHeight() const
Height is associated with y coordinate [cm].
Definition: TPCGeo.h:103
double X() const
Definition: LArVoxelID.cxx:72
virtual double ConvertTicksToX(double ticks, int p, int t, int c) const =0
geo::TPCID::TPCID_t FindTPCAtPosition(double const worldLoc[3], double const wiggle) const
Returns the index of the TPC at specified location.
double Vx(const int i=0) const
Definition: MCParticle.h:225
mapped_type Energy() const
Definition: LArVoxelData.h:209
Encapsulate the construction of a single detector plane.
size_type size() const
Definition: MCTrajectory.h:169
const TPCGeo & TPC(unsigned int itpc) const
Return the itpc&#39;th TPC in the cryostat.
Int_t min
Definition: plot.C:26
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
static const char * LatexName(int pdgcode)
Convert PDG code to a latex string (root-style)
Definition: Style.cxx:12
Float_t proj
Definition: plot.C:34
Int_t ipart
Definition: Style.C:10
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
double Pz(const int i=0) const
Definition: MCParticle.h:236
Render the objects from the Simulation package.
int fAxisOrientation
0 = TDC values on y-axis, wire number on x-axis, 1 = swapped
double Vz(const int i=0) const
Definition: MCParticle.h:227
void MCTruthOrtho(const art::Event &evt, evd::OrthoProj_t proj, double msize, evdb::View2D *view)
void MCTruthVectors2D(const art::Event &evt, evdb::View2D *view, unsigned int plane)
sim::LArVoxelID VoxelID() const
Definition: LArVoxelData.h:201
A collection of 3D drawable objects.
TCEvent evt
Definition: DataStructs.cxx:5
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:203
Float_t e
Definition: plot.C:34
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:187
Namespace collecting geometry-related classes utilities.
geo::CryostatID::CryostatID_t FindCryostatAtPosition(geo::Point_t const &worldLoc) const
Returns the index of the cryostat at specified location.
std::map< int, bool > fHighlite
double Vy(const int i=0) const
Definition: MCParticle.h:226
art framework interface to geometry description
double HalfWidth() const
Width is associated with x coordinate [cm].
Definition: TPCGeo.h:99
constexpr Point origin()
Returns a origin position with a point of the specified type.
Definition: geo_vectors.h:230
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
Cosmic rays.
Definition: MCTruth.h:22
collection_type & vals()
Definition: View.h:34
const art::Ptr< simb::MCTruth > & TrackIdToMCTruth_P(int const &id)
TPolyMarker3D & AddPolyMarker3D(int n, int c, int st, double sz)
Definition: View3D.cxx:75
Encapsulate the construction of a single detector plane.
const key_type & TrackID(const size_type) const
geo::CryostatID const & ID() const
Returns the identifier of this cryostat.
Definition: CryostatGeo.h:116
Point GetCenter() const
Returns the center of the TPC volume in world coordinates [cm].
Definition: TPCGeo.h:693