360 if (
evt.isRealData())
return;
362 art::ServiceHandle<evd::SimulationDrawingOptions const> drawopt;
364 if (!drawopt->fShowMCTruthTrajectories)
return;
366 auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(
evt);
368 art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(
evt, clockData);
369 art::ServiceHandle<geo::Geometry const> geom;
372 std::vector<const simb::MCParticle*> plist;
376 int neutralColor(12);
378 int neutrinoColor(38);
384 mf::LogDebug(
"SimulationDrawer")
385 <<
"Starting loop over " << plist.size() <<
" McParticles, voxel list size is "
386 << voxels.
size() << std::endl;
398 std::map<int, const simb::MCParticle*> trackToMcParticleMap;
401 double minPartEnergy(0.01);
403 for (
size_t p = 0;
p < plist.size(); ++
p) {
404 trackToMcParticleMap[plist[
p]->TrackId()] = plist[
p];
407 if (drawopt->fShowMCTruthTrajectories) {
409 const simb::MCParticle* mcPart = plist[
p];
410 const simb::MCTrajectory& mcTraj = mcPart->Trajectory();
412 int pdgCode(mcPart->PdgCode());
414 TParticlePDG* partPDG(TDatabasePDG::Instance()->
GetParticle(pdgCode));
415 double partCharge = partPDG ? partPDG->Charge() : 0.;
416 double partEnergy = mcPart->E();
418 if (!drawopt->fShowMCTruthColors) colorIdx = grayedColor;
420 if (!mcTraj.empty() && partEnergy > minPartEnergy && mcPart->TrackId() < 100000000) {
421 double g4Ticks(clockData.TPCG4Time2Tick(mcPart->T()) -
trigger_offset(clockData));
423 double xPosMinTick = 0.;
424 double xPosMaxTick = std::numeric_limits<double>::max();
427 int numTrajPoints = mcTraj.size();
429 std::unique_ptr<double[]> hitPositions(
new double[3 * numTrajPoints]);
432 for (
int hitIdx = 0; hitIdx < numTrajPoints; hitIdx++) {
433 double xPos = mcTraj.X(hitIdx);
434 double yPos = mcTraj.Y(hitIdx);
435 double zPos = mcTraj.Z(hitIdx);
443 geo::TPCID tpcID = geom->PositionToTPCID(hitLocation);
446 xPosMinTick =
detProp.ConvertTicksToX(0, planeID);
447 xPosMaxTick =
detProp.ConvertTicksToX(
detProp.NumberTimeSamples(), planeID);
448 xOffset =
detProp.ConvertTicksToX(g4Ticks, planeID) - xPosMinTick;
450 if (xPosMaxTick < xPosMinTick) std::swap(xPosMinTick, xPosMaxTick);
460 if (xPos > xPosMinTick && xPos < xPosMaxTick) {
470 hitPositions[3 * hitCount] = xPos;
471 hitPositions[3 * hitCount + 1] = yPos;
472 hitPositions[3 * hitCount + 2] = zPos;
477 TPolyLine3D& pl(view->AddPolyLine3D(1, colorIdx, 1, 1));
480 if (partCharge == 0.) {
481 pl.SetLineColor(neutralColor);
485 pl.SetPolyLine(hitCount, hitPositions.get(),
"");
491 std::map<const simb::MCParticle*, std::vector<std::vector<double>>> partToPosMap;
494 for (vxitr = voxels.
begin(); vxitr != voxels.
end(); vxitr++) {
498 if (vxd.
Energy(partIdx) > drawopt->fMinEnergyDeposition) {
499 int trackId = vxd.
TrackID(partIdx);
502 const simb::MCParticle* mcPart = trackToMcParticleMap[trackId];
504 partToPosMap[mcPart].push_back(std::vector<double>(3));
506 partToPosMap[mcPart].back()[0] = vxd.
VoxelID().
X();
507 partToPosMap[mcPart].back()[1] = vxd.
VoxelID().
Y();
508 partToPosMap[mcPart].back()[2] = vxd.
VoxelID().
Z();
515 std::map<const simb::MCParticle*, std::vector<std::vector<double>>>::iterator partToPosMapItr;
517 for (partToPosMapItr = partToPosMap.begin(); partToPosMapItr != partToPosMap.end();
520 const simb::MCParticle* mcPart = partToPosMapItr->first;
523 if (!mcPart || partToPosMapItr->second.empty())
continue;
525 double g4Ticks(clockData.TPCG4Time2Tick(mcPart->T()) -
trigger_offset(clockData));
527 double xPosMinTick = 0.;
528 double xPosMaxTick = std::numeric_limits<double>::max();
531 int markerIdx(kFullDotSmall);
534 if (!drawopt->fShowMCTruthFullSize) {
535 colorIdx = grayedColor;
540 std::unique_ptr<double[]> hitPositions(
new double[3 * partToPosMapItr->second.size()]);
544 for (
size_t posIdx = 0; posIdx < partToPosMapItr->second.size(); posIdx++) {
545 const std::vector<double>& posVec = partToPosMapItr->second[posIdx];
548 geo::Point_t hitLocation(posVec[0], posVec[1], posVec[2]);
551 geo::TPCID tpcID = geom->PositionToTPCID(hitLocation);
554 xPosMinTick =
detProp.ConvertTicksToX(0, planeID);
555 xPosMaxTick =
detProp.ConvertTicksToX(
detProp.NumberTimeSamples(), planeID);
556 xOffset =
detProp.ConvertTicksToX(g4Ticks, planeID) - xPosMinTick;
558 if (xPosMaxTick < xPosMinTick) std::swap(xPosMinTick, xPosMaxTick);
564 double xCoord = posVec[0] + xOffset;
568 if (xCoord > xPosMinTick && xCoord < xPosMaxTick) {
569 hitPositions[3 * hitCount] = xCoord;
570 hitPositions[3 * hitCount + 1] = posVec[1];
571 hitPositions[3 * hitCount + 2] = posVec[2];
576 TPolyMarker3D& pm = view->AddPolyMarker3D(1, colorIdx, markerIdx, markerSize);
577 pm.SetPolyMarker(hitCount, hitPositions.get(), markerIdx);
581 std::vector<const simb::MCTruth*> mctruth;
585 for (
unsigned int idx = 0; idx < mctruth.size(); idx++) {
587 for (
int particleIdx = 0; particleIdx < mctruth[idx]->NParticles(); particleIdx++) {
588 const simb::MCParticle& mcPart = mctruth[idx]->GetParticle(particleIdx);
591 if (mcPart.Mother() == -1 && mcPart.StatusCode() == 0) {
592 mf::LogDebug(
"SimulationDrawer") << mcPart << std::endl;
595 TVector3 particlePosition(mcPart.Vx(), mcPart.Vy(), mcPart.Vz());
598 TVector3 oppPartDir(-mcPart.Px(), -mcPart.Py(), -mcPart.Pz());
600 if (oppPartDir.Mag2() > 0.) oppPartDir.SetMag(1.);
602 double arcLenToDraw = -particlePosition.Z() / oppPartDir.CosTheta();
605 if (arcLenToDraw > 0.) {
607 TPolyLine3D& pl(view->AddPolyLine3D(2, neutrinoColor, 1, 2));
609 pl.SetPoint(0, particlePosition.X(), particlePosition.Y(), particlePosition.Z());
611 particlePosition += std::min(arcLenToDraw + 10., 1000.) * oppPartDir;
613 pl.SetPoint(1, particlePosition.X(), particlePosition.Y(), particlePosition.Z());
The data type to uniquely identify a Plane.
static sim::LArVoxelList GetLArVoxelList(const art::Event &evt, std::string moduleLabel)
int GetMCTruth(const art::Event &evt, std::vector< const simb::MCTruth * > &mctruth)
list_type::const_iterator const_iterator
int GetParticle(const art::Event &evt, std::vector< const simb::MCParticle * > &plist)
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.
const key_type & TrackID(const size_type) const