10 #include "TParticle.h" 12 #include "TPolyMarker3D.h" 13 #include "TPolyMarker.h" 14 #include "TPolyLine.h" 15 #include "TPolyLine3D.h" 16 #include "TDatabasePDG.h" 47 void writeErrMsg(
const char* fcn,
51 <<
" failed with message:\n" 69 for(
size_t cryoIdx = 0; cryoIdx < geom->
Ncryostats(); cryoIdx++)
73 for (
size_t tpcIdx = 0; tpcIdx < cryoGeo.
NTPC(); tpcIdx++)
77 std::cout <<
"Cryo/TPC idx: " << cryoIdx <<
"/" << tpcIdx <<
", TPC center: " << tpc.
GetCenter()[0] <<
", " << tpc.
GetCenter()[1] <<
", " << tpc.
GetCenter()[2] << std::endl;
93 std::cout <<
" minx/maxx: " <<
minx <<
"/" <<
maxx <<
", miny/maxy: " <<
miny <<
"/" <<
maxy <<
", minz/miny: " <<
minz <<
"/" <<
maxz << std::endl;
116 std::vector<const simb::MCTruth*> mctruth;
119 for (
unsigned int i=0; i<mctruth.size(); ++i) {
122 bool firstout =
true;
124 std::string incoming;
125 std::string outgoing;
128 int jmax = TMath::Min(20,mctruth[i]->NParticles());
129 for (
int j=0; j<jmax; ++j) {
133 sprintf(buff,
"#color[%d]{%s #scale[0.75]{[%.1f GeV/c]}}",
139 sprintf(buff,
"#color[%d]{%s}",
144 if (firstin==
false) incoming +=
" + ";
149 if (firstout==
false) outgoing +=
" + ";
154 if (origin==
"" && incoming==
"") {
158 mctext = origin+incoming+
" #rightarrow "+outgoing;
160 TLatex& latex = view->
AddLatex(0.03, 0.2, mctext.c_str());
161 latex.SetTextSize(0.6);
177 std::vector<const simb::MCTruth*> mctruth;
179 std::cout<<
"\nMCTruth Ptcl trackID PDG P T Moth Process\n";
180 for (
unsigned int i=0; i<mctruth.size(); ++i) {
181 for (
int j=0; j<mctruth[i]->NParticles(); ++j) {
184 int KE = 1000 * (p.
E() - p.
Mass());
185 std::cout<<
std::right<<std::setw(7)<<i<<std::setw(5)<<j
188 <<std::setw(7)<<int(1000 * p.
P())
189 <<std::setw(7)<<KE<<std::setw(7)<<p.
Mother()
201 std::cout<<
"Note: Momentum, P, and kinetic energy, T, in MeV/c\n";
222 double xyz[3] = {0.};
223 double xyz2[3] = {0.};
226 std::vector<const simb::MCTruth*> mctruth;
229 for (
size_t i = 0; i < mctruth.size(); ++i) {
231 for (
int j = 0; j < mctruth[i]->NParticles(); ++j) {
237 double r = p.
P()*10.0;
239 if (r < 0.1)
continue;
245 xyz2[0] = xyz[0] + r * p.
Px()/p.
P();
246 xyz2[1] = xyz[1] + r * p.
Py()/p.
P();
247 xyz2[2] = xyz[2] + r * p.
Pz()/p.
P();
249 double w1 = geo->WireCoordinate(xyz[1], xyz[2], (
int)plane, rawopt->
fTPC, rawopt->
fCryostat);
250 double w2 = geo->WireCoordinate(xyz2[1], xyz2[2], (
int)plane, rawopt->
fTPC, rawopt->
fCryostat);
256 TLine& l = view->
AddLine(w1, time, w2, time2);
260 TLine& l = view->
AddLine(time, w1, time2, w2);
294 std::vector<const simb::MCParticle*> plist;
304 std::cout <<
"# samples: " << theDetector->
NumberTimeSamples() <<
", min/max X: " << xMinFromTicks <<
"/" << xMaxFromTicks <<
", xMinimum/xMaximum: " << xMinimum <<
"/" << xMaximum << std::endl;
307 Color_t
const scintillationColor = kMagenta;
308 int neutralColor(12);
310 int neutrinoColor(38);
315 mf::LogDebug(
"SimulationDrawer") <<
"Starting loop over " << plist.size() <<
" McParticles, voxel list size is " << voxels.
size() << std::endl;
327 std::map<int, const simb::MCParticle*> trackToMcParticleMap;
330 constexpr
unsigned int MaxParticles = 100000000;
331 double minPartEnergy(0.01);
333 auto const* pDatabasePDG = TDatabasePDG::Instance();
335 unsigned int nDrawnParticles = 0U;
337 trackToMcParticleMap[mcPart->TrackId()] = mcPart;
344 if (mcTraj.
empty())
continue;
346 int const pdgCode(mcPart->PdgCode());
349 TParticlePDG
const* partPDG(pDatabasePDG->GetParticle(pdgCode));
350 double const partCharge = partPDG ? partPDG->Charge() : 0.;
351 double const partEnergy = mcPart->E();
355 bool const isScintillationLight = ((pdgCode == 22) || (pdgCode == 0)) && (partEnergy < 1
e-7);
357 if (isScintillationLight) {
359 if (!fDrawLight)
continue;
362 if (partEnergy < minPartEnergy)
continue;
365 if (nDrawnParticles++ >= MaxParticles) {
366 if (nDrawnParticles == MaxParticles) {
368 <<
"Only " << nDrawnParticles <<
"/" << plist.size()
369 <<
" MCParticle's will be displayed.";
399 double g4Ticks(detClocks->TPCG4Time2Tick(mcPart->T()));
402 bool xOffsetNotSet(
true);
404 int const numTrajPoints = mcTraj.
size();
406 std::vector<double> hitPositions;
407 hitPositions.reserve(3*numTrajPoints);
408 std::size_t hitCount = 0U;
411 for(
int hitIdx = 0; hitIdx < numTrajPoints; hitIdx++)
413 double xPos = mcTraj.
X(hitIdx);
414 double yPos = mcTraj.
Y(hitIdx);
415 double zPos = mcTraj.
Z(hitIdx);
418 if (xPos < minx || xPos >
maxx || yPos < miny || yPos >
maxy|| zPos < minz || zPos >
maxz)
continue;
425 auto const* pTPC = geom->PositionToTPCptr(
geo::Point_t(xPos, yPos, zPos));
432 if (xMaxFromTicks < xMinFromTicks) std::swap(xMinFromTicks,xMaxFromTicks);
434 xOffset = xMinFromTicks - theDetector->
ConvertTicksToX(g4Ticks, firstPlane);
435 xOffsetNotSet =
false;
438 catch(...) {
continue;}
445 if (xPos > xMinFromTicks && xPos < xMaxFromTicks)
456 hitPositions.push_back(xPos);
457 hitPositions.push_back(yPos);
458 hitPositions.push_back(zPos);
467 if (isScintillationLight) {
468 pl.SetLineColor(scintillationColor);
469 pl.SetLineStyle(kSolid);
472 else if (partCharge == 0.)
474 pl.SetLineColor(neutralColor);
475 pl.SetLineStyle(kDotted);
478 pl.SetPolyLine(hitCount, hitPositions.data(),
"");
483 std::map<const simb::MCParticle*, std::vector<std::vector<double> > > partToPosMap;
486 for(vxitr = voxels.
begin(); vxitr != voxels.
end(); vxitr++)
494 int trackId = vxd.
TrackID(partIdx);
499 partToPosMap[mcPart].push_back(std::vector<double>(3));
501 partToPosMap[mcPart].back()[0] = vxd.
VoxelID().
X();
502 partToPosMap[mcPart].back()[1] = vxd.
VoxelID().
Y();
503 partToPosMap[mcPart].back()[2] = vxd.
VoxelID().
Z();
510 std::map<const simb::MCParticle*, std::vector<std::vector<double> > >
::iterator partToPosMapItr;
512 for(partToPosMapItr = partToPosMap.begin(); partToPosMapItr != partToPosMap.end(); partToPosMapItr++)
518 if (!mcPart || partToPosMapItr->second.empty())
continue;
524 double g4Ticks(detClocks->TPCG4Time2Tick(mcPart->
T()));
527 bool xOffsetNotSet(
true);
530 int markerIdx(kFullDotSmall);
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++)
546 const std::vector<double>& posVec = partToPosMapItr->second[posIdx];
551 double hitLocation[] = {posVec[0],posVec[1],posVec[2]};
561 if (xMaxFromTicks < xMinFromTicks) std::swap(xMinFromTicks,xMaxFromTicks);
564 xOffsetNotSet =
false;
567 catch(...) {
continue;}
570 double xCoord = posVec[0] + xOffset;
572 if (xCoord > xMinFromTicks && xCoord < xMaxFromTicks)
574 hitPositions[3*hitCount ] = xCoord;
575 hitPositions[3*hitCount + 1] = posVec[1];
576 hitPositions[3*hitCount + 2] = posVec[2];
581 TPolyMarker3D& pm = view->
AddPolyMarker3D(1, colorIdx, markerIdx, markerSize);
582 pm.SetPolyMarker(hitCount, hitPositions.get(), markerIdx);
586 std::vector<const simb::MCTruth*> mctruth;
590 for (
unsigned int idx = 0; idx < mctruth.size(); idx++)
593 for (
int particleIdx = 0; particleIdx < mctruth[idx]->NParticles(); particleIdx++)
600 mf::LogDebug(
"SimulationDrawer") << mcPart << std::endl;
603 TVector3 particlePosition(mcPart.
Vx(),mcPart.
Vy(),mcPart.
Vz());
606 TVector3 oppPartDir(-mcPart.
Px(),-mcPart.
Py(),-mcPart.
Pz());
608 if (oppPartDir.Mag2() > 0.) oppPartDir.SetMag(1.);
610 double arcLenToDraw = -particlePosition.Z() / oppPartDir.CosTheta();
613 if (arcLenToDraw > 0.)
616 TPolyLine3D& pl(view->
AddPolyLine3D(2, neutrinoColor, 1, 2));
618 pl.SetPoint(0,particlePosition.X(),particlePosition.Y(),particlePosition.Z());
620 particlePosition +=
std::min(arcLenToDraw + 10.,1000.) * oppPartDir;
622 pl.SetPoint(1,particlePosition.X(),particlePosition.Y(),particlePosition.Z());
652 std::vector<const simb::MCParticle*> plist;
668 mf::LogDebug(
"SimulationDrawer") <<
"Starting loop over " << plist.size() <<
" McParticles, voxel list size is " << voxels.
size() << std::endl;
680 std::map<int, const simb::MCParticle*> trackToMcParticleMap;
683 bool displayMcTrajectories(
true);
684 double minPartEnergy(0.025);
686 double tpcminx = 1.0;
double tpcmaxx = -1.0;
687 double xOffset = 0.0;
double g4Ticks = 0.0;
688 double coeff = 0.0;
double readoutwindowsize = 0.0;
689 double vtx[3] = {0.0, 0.0, 0.0};
690 for(
size_t p = 0; p < plist.size(); ++p)
692 trackToMcParticleMap[plist[p]->TrackId()] = plist[p];
695 if (displayMcTrajectories)
701 int pdgCode(mcPart->
PdgCode());
702 TParticlePDG* partPDG(TDatabasePDG::Instance()->
GetParticle(pdgCode));
703 double partCharge = partPDG ? partPDG->Charge() : 0.;
704 double partEnergy = mcPart->
E();
706 if (!mcTraj.
empty() && partEnergy > minPartEnergy && mcPart->
TrackId() < 100000000)
709 int numTrajPoints = mcTraj.
size();
711 std::unique_ptr<double[]> hitPosX(
new double[numTrajPoints]);
712 std::unique_ptr<double[]> hitPosY(
new double[numTrajPoints]);
713 std::unique_ptr<double[]> hitPosZ(
new double[numTrajPoints]);
716 double xPos = mcTraj.
X(0);
717 double yPos = mcTraj.
Y(0);
718 double zPos = mcTraj.
Z(0);
720 tpcminx = 1.0; tpcmaxx = -1.0;
721 xOffset = 0.0; g4Ticks = 0.0;
722 vtx[0] = 0.0; vtx[1] = 0.0; vtx[2] = 0.0;
723 coeff = 0.0; readoutwindowsize = 0.0;
724 for(
int hitIdx = 0; hitIdx < numTrajPoints; hitIdx++)
726 xPos = mcTraj.
X(hitIdx);
727 yPos = mcTraj.
Y(hitIdx);
728 zPos = mcTraj.
Z(hitIdx);
731 if (xPos < minx || xPos >
maxx || yPos < miny || yPos >
maxy|| zPos < minz || zPos >
maxz)
continue;
733 if ((xPos < tpcminx) || (xPos > tpcmaxx))
735 vtx[0] = xPos; vtx[1] = yPos; vtx[2] = zPos;
741 unsigned int tpc = tpcid.
TPC;
743 tpcminx = tpcgeo.
MinX(); tpcmaxx = tpcgeo.
MaxX();
745 coeff = theDetector->GetXTicksCoefficient(tpc, cryo);
746 readoutwindowsize = theDetector->ConvertTicksToX(theDetector->ReadOutWindowSize(), 0, tpc, cryo);
750 g4Ticks = detClocks->TPCG4Time2Tick(mcPart->
T())
751 +theDetector->GetXTicksOffset(0, tpc, cryo)
752 -theDetector->TriggerOffset();
754 xOffset = theDetector->ConvertTicksToX(g4Ticks, 0, tpc, cryo);
756 else { xOffset = 0; tpcminx = 1.0; tpcmaxx = -1.0; coeff = 0.0; readoutwindowsize = 0.0;}
762 bool inreadoutwindow =
false;
765 if ((xPos > readoutwindowsize) && (xPos < tpcmaxx)) inreadoutwindow =
true;
769 if ((xPos > tpcminx) && (xPos < readoutwindowsize)) inreadoutwindow =
true;
772 if (!inreadoutwindow)
continue;
775 if (xPos > xMinimum && xPos < xMaximum)
777 hitPosX[hitCount] = xPos;
778 hitPosY[hitCount] = yPos;
779 hitPosZ[hitCount] = zPos;
788 if (partCharge == 0.)
796 pl.SetPolyLine(hitCount, hitPosX.get(), hitPosY.get(),
"");
798 pl.SetPolyLine(hitCount, hitPosZ.get(), hitPosX.get(),
"");
800 pl.SetPolyLine(hitCount, hitPosZ.get(), hitPosY.get(),
"");
806 std::map<const simb::MCParticle*, std::vector<std::vector<double> > > partToPosMap;
809 for(vxitr = voxels.
begin(); vxitr != voxels.
end(); vxitr++)
817 int trackId = vxd.
TrackID(partIdx);
822 partToPosMap[mcPart].push_back(std::vector<double>(3));
824 partToPosMap[mcPart].back()[0] = vxd.
VoxelID().
X();
825 partToPosMap[mcPart].back()[1] = vxd.
VoxelID().
Y();
826 partToPosMap[mcPart].back()[2] = vxd.
VoxelID().
Z();
833 std::map<const simb::MCParticle*, std::vector<std::vector<double> > >
::iterator partToPosMapItr;
835 for(partToPosMapItr = partToPosMap.begin(); partToPosMapItr != partToPosMap.end(); partToPosMapItr++)
841 if (!mcPart || partToPosMapItr->second.empty())
continue;
843 tpcminx = 1.0; tpcmaxx = -1.0;
844 xOffset = 0.0; g4Ticks = 0.0;
845 std::vector< std::array<double, 3> > posVecCorr;
846 posVecCorr.reserve(partToPosMapItr->second.size());
847 coeff = 0.0; readoutwindowsize = 0.0;
850 for(
size_t posIdx = 0; posIdx < partToPosMapItr->second.size(); posIdx++)
852 const std::vector<double>& posVec = partToPosMapItr->second[posIdx];
854 if ((posVec[0] < tpcminx) || (posVec[0] > tpcmaxx))
856 vtx[0] = posVec[0]; vtx[1] = posVec[1]; vtx[2] = posVec[2];
862 unsigned int tpc = tpcid.
TPC;
865 tpcminx = tpcgeo.
MinX(); tpcmaxx = tpcgeo.
MaxX();
867 coeff = theDetector->GetXTicksCoefficient(tpc, cryo);
868 readoutwindowsize = theDetector->ConvertTicksToX(theDetector->ReadOutWindowSize(), 0, tpc, cryo);
871 g4Ticks = detClocks->TPCG4Time2Tick(mcPart->
T())
872 +theDetector->GetXTicksOffset(0, tpc, cryo)
873 -theDetector->TriggerOffset();
875 xOffset = theDetector->ConvertTicksToX(g4Ticks, 0, tpc, cryo);
877 else { xOffset = 0; tpcminx = 1.0; tpcmaxx = -1.0; coeff = 0.0; readoutwindowsize = 0.0; }
880 double xCoord = posVec[0] + xOffset;
882 bool inreadoutwindow =
false;
885 if ((xCoord > readoutwindowsize) && (xCoord < tpcmaxx)) inreadoutwindow =
true;
889 if ((xCoord > tpcminx) && (xCoord < readoutwindowsize)) inreadoutwindow =
true;
892 if (inreadoutwindow && (xCoord > xMinimum && xCoord < xMaximum))
894 posVecCorr.push_back({{xCoord, posVec[1], posVec[2] }});
900 for (
size_t p = 0; p < posVecCorr.size(); ++p)
903 pm.SetPoint(p, posVecCorr[p][0], posVecCorr[p][1]);
905 pm.SetPoint(p, posVecCorr[p][2], posVecCorr[p][0]);
907 pm.SetPoint(p, posVecCorr[p][2], posVecCorr[p][1]);
916 std::vector<const simb::MCParticle*>& plist)
924 std::vector<const simb::MCParticle*> temp;
930 for(
unsigned int i = 0; i < plcol.
vals().size(); ++i){
931 temp.push_back(plcol.
vals().at(i));
936 writeErrMsg(
"GetRawDigits", e);
946 std::vector<const simb::MCTruth*>& mcvec)
952 std::vector<const simb::MCTruth*> temp;
954 std::vector< art::Handle< std::vector<simb::MCTruth> > > mctcol;
958 for(
size_t mctc = 0; mctc < mctcol.size(); ++mctc){
961 for(
size_t i = 0; i < mclistHandle->size(); ++i){
962 temp.push_back(&(mclistHandle->at(i)));
968 writeErrMsg(
"GetMCTruth", e);
double E(const int i=0) const
double Z(const size_type i) const
double X(const size_type i) const
Point GetActiveVolumeCenter() const
Returns the center of the TPC active volume in world coordinates [cm].
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
double Py(const int i=0) const
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.
void HiLite(int trkId, bool hlt=true)
TPolyLine & AddPolyLine(int n, int c, int w, int s)
std::string fG4ModuleLabel
module label producing sim::SimChannel objects
Container of LAr voxel information.
double ActiveHalfHeight() const
Half height (associated with y coordinate) of active TPC volume [cm].
const simb::MCTrajectory & Trajectory() const
TLine & AddLine(double x1, double y1, double x2, double y2)
double MinX() const
Returns the world x coordinate of the start of the box.
The data type to uniquely identify a Plane.
bool isValid
Whether this ID points to a valid element.
Geometry information for a single TPC.
double Px(const int i=0) const
static sim::LArVoxelList GetLArVoxelList(const art::Event &evt, std::string moduleLabel)
CryostatID_t Cryostat
Index of cryostat.
int GetMCTruth(const art::Event &evt, std::vector< const simb::MCTruth * > &mctruth)
double MaxX() const
Returns the world x coordinate of the end of the box.
A collection of drawable 2-D objects.
static void FromPDG(TLine &line, int pdgcode)
Geometry information for a single cryostat.
unsigned int Ncryostats() const
Returns the number of cryostats in the detector.
std::string Process() const
void MCTruth3D(const art::Event &evt, evdb::View3D *view)
virtual double ConvertXToTicks(double X, int p, int t, int c) const =0
double Length() const
Length is associated with z coordinate [cm].
list_type::const_iterator const_iterator
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)
std::size_t getView(std::string const &moduleLabel, std::string const &productInstanceName, std::vector< ELEMENT const * > &result) const
double Y(const size_type i) const
Encapsulates the information we want store for a voxel.
unsigned int fCryostat
Cryostat number to draw, typically set by TWQProjectionView.
double ActiveHalfWidth() const
Half width (associated with x coordinate) of active TPC volume [cm].
int GetParticle(const art::Event &evt, std::vector< const simb::MCParticle * > &plist)
double P(const int i=0) const
TPolyMarker & AddPolyMarker(int n, int c, int st, double sz)
static int ColorFromPDG(int pdgcode)
double T(const int i=0) const
double fMinEnergyDeposition
bool fShowMCTruthTrajectories
void getManyByType(std::vector< Handle< PROD >> &results) const
unsigned int NTPC() const
Number of TPCs in this cryostat.
size_type NumberParticles() const
CryostatGeo const & Cryostat(geo::CryostatID const &cryoid) const
Returns the specified cryostat.
virtual unsigned int NumberTimeSamples() const =0
The data type to uniquely identify a TPC.
Description of geometry of one entire detector.
TLatex & AddLatex(double x, double y, const char *text)
double ActiveLength() const
Length (associated with z coordinate) of active TPC volume [cm].
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.
double HalfHeight() const
Height is associated with y coordinate [cm].
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
mapped_type Energy() const
Encapsulate the construction of a single detector plane.
const TPCGeo & TPC(unsigned int itpc) const
Return the itpc'th TPC in the cryostat.
virtual double DriftVelocity(double efield=0., double temperature=0.) const =0
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
static const char * LatexName(int pdgcode)
Convert PDG code to a latex string (root-style)
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
double Pz(const int i=0) const
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
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
A collection of 3D drawable objects.
TPCID_t TPC
Index of the TPC within its cryostat.
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
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
art framework interface to geometry description
double HalfWidth() const
Width is associated with x coordinate [cm].
constexpr Point origin()
Returns a origin position with a point of the specified type.
cet::coded_exception< error, detail::translate > exception
TPolyMarker3D & AddPolyMarker3D(int n, int c, int st, double sz)
Encapsulate the construction of a single detector plane.
bool fShowMCTruthFullSize
const key_type & TrackID(const size_type) const
geo::CryostatID const & ID() const
Returns the identifier of this cryostat.
Point GetCenter() const
Returns the center of the TPC volume in world coordinates [cm].