DrawSimEnergyDeposit3D_tool.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 /// \file DrawSimEnergyDeposit3D_tool.cc
3 /// \author T. Usher
4 ////////////////////////////////////////////////////////////////////////
5 
8 
13 
17 
22 
23 #include "TPolyMarker3D.h"
24 
25 namespace evdb_tool {
26 
28  public:
29  explicit DrawSimEnergyDeposit3D(const fhicl::ParameterSet& pset);
30 
31  void Draw(const art::Event&, evdb::View3D*) const override;
32 
33  private:
34  void drawMCPartAssociated(const art::Event&, evdb::View3D*) const;
35  void drawAll(const art::Event&, evdb::View3D*) const;
36 
38  };
39 
40  //----------------------------------------------------------------------
41  // Constructor.
43  {
44  fDrawAllSimEnergy = pset.get<bool>("DrawAllSimEnergyDeposits", false);
45  }
46 
47  void
48  DrawSimEnergyDeposit3D::Draw(const art::Event& evt, evdb::View3D* view) const
49  {
51 
52  // If the option is turned off, there's nothing to do
53  if (!drawOpt->fShowSimEnergyInfo) return;
54 
55  // Split here if drawing all vs drawing MC associated only
57  drawAll(evt, view);
58  else
59  drawMCPartAssociated(evt, view);
60 
61  return;
62  }
63 
64  void
66  {
68 
69  // Recover a handle to the collection of MCParticles
70  // We need these so we can determine the offset (if any)
72 
73  evt.getByLabel(drawOpt->fG4ModuleLabel, mcParticleHandle);
74 
75  if (!mcParticleHandle.isValid()) return;
76 
77  // Create a mapping between track ID's and MCParticles
78  using TrackToMcParticleMap = std::map<int, const simb::MCParticle*>;
79 
80  TrackToMcParticleMap trackToMcParticleMap;
81 
82  for (const auto& mcParticle : *mcParticleHandle)
83  trackToMcParticleMap[mcParticle.TrackId()] = &mcParticle;
84 
85  // Now recover the simchannels
86  art::Handle<std::vector<sim::SimEnergyDeposit>> simEnergyDepositHandle;
87 
88  evt.getByLabel(drawOpt->fSimEnergyLabel, simEnergyDepositHandle);
89 
90  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(evt);
91  auto const detProp =
93 
94  if (simEnergyDepositHandle.isValid() && simEnergyDepositHandle->size() > 0) {
95  mf::LogDebug("SimEnergyDeposit3DDrawer")
96  << "Starting loop over " << simEnergyDepositHandle->size() << " SimEnergyDeposits, "
97  << std::endl;
98 
100 
101  // First step is to create a map between MCParticle and SimEnergyDeposit objects...
102  using MCPartToSimEnergyMap =
103  std::map<const simb::MCParticle*, std::vector<const sim::SimEnergyDeposit*>>;
104 
105  MCPartToSimEnergyMap mcPartToSimEnergyMap;
106 
107  // Go through the SimEnergyDeposits and populate the map
108  for (const auto& simEnergyDeposit : *simEnergyDepositHandle) {
110  trackToMcParticleMap.find(simEnergyDeposit.TrackID());
111 
112  if (trackMCItr == trackToMcParticleMap.end()) continue;
113 
114  mcPartToSimEnergyMap[trackMCItr->second].push_back(&simEnergyDeposit);
115  }
116 
117  // Would like to draw the deposits as markers with colors given by particle id
118  // So we make two passes, first to fill a map with color the key and positions for the markers
119  std::map<int, std::vector<sim::SimEnergyDeposit::Point_t>> colorToPositionMap;
120 
121  // Now we loop through and build the mapping of color to positions
122  for (const auto& mcPartToSimEnergy : mcPartToSimEnergyMap) {
123  // The first task we need to take on is to find the offset for the
124  // energy deposit This is for the case of "out of time" particles...
125  // (e.g. cosmic rays)
126  double g4Ticks(clockData.TPCG4Time2Tick(mcPartToSimEnergy.first->T()) -
127  trigger_offset(clockData));
128  double xOffset(0.);
129  double xPosMinTick(0.);
130  double xPosMaxTick(std::numeric_limits<double>::max());
131 
132  for (const auto& simEnergyDeposit : mcPartToSimEnergy.second) {
133  sim::SimEnergyDeposit::Point_t point = simEnergyDeposit->MidPoint();
134 
135  // If we have cosmic rays then we need to get the offset which allows translating from
136  // when they were generated vs when they were tracked.
137  // Note that this also explicitly checks that they are in a TPC volume
138  try {
139  geo::TPCID tpcID = geom->PositionToTPCID(point);
140  geo::PlaneID planeID(tpcID, 0);
141 
142  xPosMinTick = detProp.ConvertTicksToX(0, planeID);
143  xPosMaxTick = detProp.ConvertTicksToX(detProp.NumberTimeSamples(), planeID);
144  xOffset = detProp.ConvertTicksToX(g4Ticks, planeID) - xPosMinTick;
145 
146  if (xPosMaxTick < xPosMinTick) std::swap(xPosMinTick, xPosMaxTick);
147  }
148  catch (...) {
149  continue;
150  }
151 
152  colorToPositionMap[evd::Style::ColorFromPDG(simEnergyDeposit->PdgCode())].emplace_back(
153  sim::SimEnergyDeposit::Point_t(point.X() + xOffset, point.Y(), point.Z()));
154  }
155  }
156 
157  // Now we can do some drawing
158  for (const auto& pair : colorToPositionMap) {
159  int colorIdx(pair.first);
160  int markerIdx(kFullDotMedium);
161  int markerSize(2);
162 
163  TPolyMarker3D& pm = view->AddPolyMarker3D(1, colorIdx, markerIdx, markerSize);
164 
165  // Import positions into an array
166  std::vector<double> posArrayVec;
167  int hitCount(0);
168 
169  posArrayVec.resize(3 * pair.second.size());
170 
171  for (const auto& point : pair.second) {
172  posArrayVec[3 * hitCount] = point.X();
173  posArrayVec[3 * hitCount + 1] = point.Y();
174  posArrayVec[3 * hitCount + 2] = point.Z();
175  hitCount++;
176  }
177 
178  pm.SetPolyMarker(hitCount, posArrayVec.data(), markerIdx);
179  }
180  }
181 
182  return;
183  }
184 
185  void
186  DrawSimEnergyDeposit3D::drawAll(const art::Event& evt, evdb::View3D* view) const
187  {
189 
190  // NOTE: In this mode we cannot correct the voxel positions for time offsets since we have nothing to offset with
191  // The voxels are drawn in the x,y,z locations given by the SimEnergyDeposit objects
192 
193  // Recover the simchannels
194  art::Handle<std::vector<sim::SimEnergyDeposit>> simEnergyDepositHandle;
195 
196  evt.getByLabel(drawOpt->fSimEnergyLabel, simEnergyDepositHandle);
197 
198  if (simEnergyDepositHandle.isValid() && simEnergyDepositHandle->size() > 0) {
199  mf::LogDebug("SimEnergyDeposit3DDrawer")
200  << "Starting loop over " << simEnergyDepositHandle->size() << " SimEnergyDeposits, "
201  << std::endl;
202 
203  // Get the geometry service and its friends
204  auto const clockData =
206  auto const detProp =
209 
210  // Would like to draw the deposits as markers with colors given by particle id
211  // So we make two passes, first to fill a map with color the key and positions for the markers
212  std::map<int, std::vector<sim::SimEnergyDeposit::Point_t>> colorToPositionMap;
213 
214  // Go through the SimEnergyDeposits and populate the map
215  for (const auto& simEnergyDeposit : *simEnergyDepositHandle) {
216  // If we have cosmic rays then we need to get the offset which allows translating from
217  // when they were generated vs when they were tracked.
218  // Note that this also explicitly checks that they are in a TPC volume
219  try {
220  sim::SimEnergyDeposit::Point_t point = simEnergyDeposit.MidPoint();
221  double depTime = simEnergyDeposit.T();
222  geo::TPCID tpcID = geom->PositionToTPCID(point);
223  geo::PlaneID planeID(tpcID, 0);
224  double g4Ticks = clockData.TPCG4Time2Tick(depTime) - trigger_offset(clockData);
225  double xPosMinTick = detProp.ConvertTicksToX(0, planeID);
226  double xOffset = detProp.ConvertTicksToX(g4Ticks, planeID) - xPosMinTick;
227 
228  colorToPositionMap[evd::Style::ColorFromPDG(simEnergyDeposit.PdgCode())].emplace_back(
229  sim::SimEnergyDeposit::Point_t(point.X() + xOffset, point.Y(), point.Z()));
230  }
231  catch (...) {
232  continue;
233  }
234  }
235 
236  // Now we can do some drawing
237  for (const auto& pair : colorToPositionMap) {
238  int colorIdx(pair.first);
239  int markerIdx(kFullDotMedium);
240  int markerSize(2);
241 
242  TPolyMarker3D& pm = view->AddPolyMarker3D(1, colorIdx, markerIdx, markerSize);
243 
244  // Import positions into an array
245  std::vector<double> posArrayVec;
246  int hitCount(0);
247 
248  posArrayVec.resize(3 * pair.second.size());
249 
250  for (const auto& point : pair.second) {
251  posArrayVec[3 * hitCount] = point.X();
252  posArrayVec[3 * hitCount + 1] = point.Y();
253  posArrayVec[3 * hitCount + 2] = point.Z();
254  hitCount++;
255  }
256 
257  pm.SetPolyMarker(hitCount, posArrayVec.data(), markerIdx);
258  }
259  }
260 
261  return;
262  }
263 
265 }
#define DEFINE_ART_CLASS_TOOL(tool)
Definition: ToolMacros.h:42
The data type to uniquely identify a Plane.
Definition: geo_types.h:472
void drawAll(const art::Event &, evdb::View3D *) const
art::InputTag fG4ModuleLabel
module label producing sim::SimChannel objects
geo::TPCID PositionToTPCID(geo::Point_t const &point) const
Returns the ID of the TPC at specified location.
void drawMCPartAssociated(const art::Event &, evdb::View3D *) const
intermediate_table::const_iterator const_iterator
Particle class.
art framework interface to geometry description
DrawSimEnergyDeposit3D(const fhicl::ParameterSet &pset)
bool isValid() const noexcept
Definition: Handle.h:191
bool getByLabel(std::string const &label, std::string const &instance, Handle< PROD > &result) const
Definition: DataViewImpl.h:633
void swap(Handle< T > &a, Handle< T > &b)
void Draw(const art::Event &, evdb::View3D *) const override
T get(std::string const &key) const
Definition: ParameterSet.h:271
static int ColorFromPDG(int pdgcode)
Definition: Style.cxx:65
static int max(int a, int b)
The data type to uniquely identify a TPC.
Definition: geo_types.h:386
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
contains information for a single step in the detector simulation
int trigger_offset(DetectorClocksData const &data)
TCEvent evt
Definition: DataStructs.cxx:7
QTextStream & endl(QTextStream &s)
art::InputTag fSimEnergyLabel
Also for SimEnergyDeposits.