17 #include "nuevdb/EventDisplayBase/View3D.h"
18 #include "nusimdata/SimulationBase/MCParticle.h"
19 #include "nusimdata/SimulationBase/MCTruth.h"
21 #include "art/Framework/Principal/Event.h"
22 #include "art/Framework/Services/Registry/ServiceHandle.h"
23 #include "art/Utilities/ToolMacros.h"
24 #include "cetlib_except/exception.h"
25 #include "messagefacility/MessageLogger/MessageLogger.h"
27 #include "TDatabasePDG.h"
28 #include "TPolyLine3D.h"
29 #include "TPolyMarker3D.h"
37 void Draw(
const art::Event&, evdb::View3D*)
const override;
40 int GetMCTruth(
const art::Event&, std::vector<const simb::MCTruth*>&)
const;
50 art::ServiceHandle<evd::SimulationDrawingOptions const> drawOpt;
53 if (!drawOpt->fShowSimChannelInfo)
return;
56 if (!drawOpt->fShowMCTruthTrajectories)
return;
58 auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(evt);
60 art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(evt, clockData);
61 art::ServiceHandle<geo::Geometry const> geom;
64 art::Handle<std::vector<simb::MCParticle>> mcParticleHandle;
66 evt.getByLabel(drawOpt->fG4ModuleLabel, mcParticleHandle);
68 if (!mcParticleHandle.isValid())
return;
73 int neutrinoColor(38);
79 mf::LogDebug(
"SimulationDrawer")
80 <<
"Starting loop over " << mcParticleHandle->
size() <<
" McParticles, voxel list size is "
81 << voxels.
size() << std::endl;
93 std::map<int, const simb::MCParticle*> trackToMcParticleMap;
96 double minPartEnergy(0.01);
98 for (
size_t p = 0;
p < mcParticleHandle->size(); ++
p) {
99 art::Ptr<simb::MCParticle> mcParticle(mcParticleHandle,
p);
101 trackToMcParticleMap[mcParticle->TrackId()] = mcParticle.get();
104 if (drawOpt->fShowMCTruthTrajectories) {
106 const simb::MCTrajectory& mcTraj = mcParticle->Trajectory();
108 int pdgCode(mcParticle->PdgCode());
110 TParticlePDG* partPDG(TDatabasePDG::Instance()->GetParticle(pdgCode));
111 double partCharge = partPDG ? partPDG->Charge() : 0.;
112 double partEnergy = mcParticle->E();
114 if (!drawOpt->fShowMCTruthColors) colorIdx = grayedColor;
116 if (!mcTraj.empty() && partEnergy > minPartEnergy && mcParticle->TrackId() < 100000000) {
117 double g4Ticks(clockData.TPCG4Time2Tick(mcParticle->T()) -
trigger_offset(clockData));
119 double xPosMinTick = 0.;
120 double xPosMaxTick = std::numeric_limits<double>::max();
123 int numTrajPoints = mcTraj.size();
125 std::unique_ptr<double[]> hitPositions(
new double[3 * numTrajPoints]);
128 for (
int hitIdx = 0; hitIdx < numTrajPoints; hitIdx++) {
129 double xPos = mcTraj.X(hitIdx);
130 double yPos = mcTraj.Y(hitIdx);
131 double zPos = mcTraj.Z(hitIdx);
139 geo::TPCID tpcID = geom->PositionToTPCID(hitLocation);
142 xPosMinTick =
detProp.ConvertTicksToX(0, planeID);
143 xPosMaxTick =
detProp.ConvertTicksToX(
detProp.NumberTimeSamples(), planeID);
144 xOffset =
detProp.ConvertTicksToX(g4Ticks, planeID) - xPosMinTick;
146 if (xPosMaxTick < xPosMinTick) std::swap(xPosMinTick, xPosMaxTick);
156 if (xPos > xPosMinTick && xPos < xPosMaxTick) {
157 hitPositions[3 * hitCount] = xPos;
158 hitPositions[3 * hitCount + 1] = yPos;
159 hitPositions[3 * hitCount + 2] = zPos;
164 TPolyLine3D& pl(view->AddPolyLine3D(1, colorIdx, 1, 1));
167 if (partCharge == 0.) {
168 pl.SetLineColor(neutralColor);
172 pl.SetPolyLine(hitCount, hitPositions.get(),
"");
178 std::map<const simb::MCParticle*, std::vector<std::vector<double>>> partToPosMap;
181 for (vxitr = voxels.
begin(); vxitr != voxels.
end(); vxitr++) {
185 if (vxd.
Energy(partIdx) > drawOpt->fMinEnergyDeposition) {
186 int trackId = vxd.
TrackID(partIdx);
189 const simb::MCParticle* mcPart = trackToMcParticleMap[trackId];
191 partToPosMap[mcPart].push_back(std::vector<double>(3));
193 partToPosMap[mcPart].back()[0] = vxd.
VoxelID().
X();
194 partToPosMap[mcPart].back()[1] = vxd.
VoxelID().
Y();
195 partToPosMap[mcPart].back()[2] = vxd.
VoxelID().
Z();
202 std::map<const simb::MCParticle*, std::vector<std::vector<double>>>::iterator partToPosMapItr;
204 for (partToPosMapItr = partToPosMap.begin(); partToPosMapItr != partToPosMap.end();
207 const simb::MCParticle* mcPart = partToPosMapItr->first;
210 if (!mcPart || partToPosMapItr->second.empty())
continue;
212 double g4Ticks(clockData.TPCG4Time2Tick(mcPart->T()) -
trigger_offset(clockData));
214 double xPosMinTick = 0.;
215 double xPosMaxTick = std::numeric_limits<double>::max();
218 int markerIdx(kFullDotSmall);
221 if (!drawOpt->fShowMCTruthFullSize) {
222 colorIdx = grayedColor;
227 std::unique_ptr<double[]> hitPositions(
new double[3 * partToPosMapItr->second.size()]);
231 for (
size_t posIdx = 0; posIdx < partToPosMapItr->second.size(); posIdx++) {
232 const std::vector<double>& posVec = partToPosMapItr->second[posIdx];
235 geo::Point_t hitLocation(posVec[0], posVec[1], posVec[2]);
238 geo::TPCID tpcID = geom->PositionToTPCID(hitLocation);
241 xPosMinTick =
detProp.ConvertTicksToX(0, planeID);
242 xPosMaxTick =
detProp.ConvertTicksToX(
detProp.NumberTimeSamples(), planeID);
243 xOffset =
detProp.ConvertTicksToX(g4Ticks, planeID) - xPosMinTick;
245 if (xPosMaxTick < xPosMinTick) std::swap(xPosMinTick, xPosMaxTick);
251 double xCoord = posVec[0] + xOffset;
255 if (xCoord > xPosMinTick && xCoord < xPosMaxTick) {
256 hitPositions[3 * hitCount] = xCoord;
257 hitPositions[3 * hitCount + 1] = posVec[1];
258 hitPositions[3 * hitCount + 2] = posVec[2];
263 TPolyMarker3D& pm = view->AddPolyMarker3D(1, colorIdx, markerIdx, markerSize);
264 pm.SetPolyMarker(hitCount, hitPositions.get(), markerIdx);
268 std::vector<const simb::MCTruth*> mctruth;
272 for (
unsigned int idx = 0; idx < mctruth.size(); idx++) {
274 for (
int particleIdx = 0; particleIdx < mctruth[idx]->NParticles(); particleIdx++) {
275 const simb::MCParticle& mcPart = mctruth[idx]->GetParticle(particleIdx);
278 if (mcPart.Mother() == -1 && mcPart.StatusCode() == 0) {
279 mf::LogDebug(
"SimulationDrawer") << mcPart << std::endl;
282 TVector3 particlePosition(mcPart.Vx(), mcPart.Vy(), mcPart.Vz());
285 TVector3 oppPartDir(-mcPart.Px(), -mcPart.Py(), -mcPart.Pz());
287 if (oppPartDir.Mag2() > 0.) oppPartDir.SetMag(1.);
289 double arcLenToDraw = -particlePosition.Z() / oppPartDir.CosTheta();
292 if (arcLenToDraw > 0.) {
294 TPolyLine3D& pl(view->AddPolyLine3D(2, neutrinoColor, 1, 2));
296 pl.SetPoint(0, particlePosition.X(), particlePosition.Y(), particlePosition.Z());
298 particlePosition += std::min(arcLenToDraw + 10., 1000.) * oppPartDir;
300 pl.SetPoint(1, particlePosition.X(), particlePosition.Y(), particlePosition.Z());
318 if (evt.isRealData())
return 0;
320 std::vector<const simb::MCTruth*> temp;
322 std::vector<art::Handle<std::vector<simb::MCTruth>>> mctcol;
327 mctcol = evt.getMany<std::vector<simb::MCTruth>>();
329 for (
size_t mctc = 0; mctc < mctcol.size(); ++mctc) {
330 art::Handle<std::vector<simb::MCTruth>> mclistHandle = mctcol[mctc];
332 for (
size_t i = 0; i < mclistHandle->size(); ++i) {
333 temp.push_back(&(mclistHandle->at(i)));
338 catch (cet::exception&
e) {
339 mf::LogWarning(
"DrawLArVoxel3D") <<
"GetMCTruth:"
340 <<
" failed with message:\n"
Container of LAr voxel information.
The data type to uniquely identify a Plane.
static sim::LArVoxelList GetLArVoxelList(const art::Event &evt, std::string moduleLabel)
list_type::const_iterator const_iterator
Encapsulates the information we want store for a voxel.
static int ColorFromPDG(int pdgcode)
size_type NumberParticles() const
The data type to uniquely identify a TPC.
mapped_type Energy() const
int trigger_offset(DetectorClocksData const &data)
sim::LArVoxelID VoxelID() const
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
art framework interface to geometry description
const key_type & TrackID(const size_type) const