491 std::vector<std::pair<geo::WireID, const sim::IDE *>>
empty;
492 const std::vector<std::pair<geo::WireID, const sim::IDE *>> &particle_ides = id_to_ide_map.count(particle.TrackId()) ? id_to_ide_map.at(particle.TrackId()) : empty;
494 std::vector<art::Ptr<recob::Hit>> emptyHits;
495 const std::vector<art::Ptr<recob::Hit>> &particle_hits = id_to_truehit_map.count(particle.TrackId()) ? id_to_truehit_map.at(particle.TrackId()) : emptyHits;
509 for (
auto const &ide_pair: particle_ides) {
511 const sim::IDE *ide = ide_pair.second;
516 else if (w.
Plane == 1) {
519 else if (w.
Plane == 2) {
524 for (
const art::Ptr<recob::Hit>
h: particle_hits) {
530 else if (w.
Plane == 1) {
533 else if (w.
Plane == 2) {
540 trueparticle.
cont_tpc = particle.NumberTrajectoryPoints() > 0;
541 trueparticle.
contained = particle.NumberTrajectoryPoints() > 0;
544 int entry_point = -1;
546 int cryostat_index = -1;
549 for (
unsigned j = 0; j < particle.NumberTrajectoryPoints(); j++) {
550 for (
unsigned i = 0; i < active_volumes.size(); i++) {
551 if (active_volumes.at(i).ContainsPosition(particle.Position(j).Vect())) {
557 if (entry_point != -1)
break;
561 if (entry_point > 0) {
562 trueparticle.
wallin = (int)
caf::GetWallCross(active_volumes.at(cryostat_index), particle.Position(entry_point).Vect(), particle.Position(entry_point-1).Vect());
568 std::vector<geo::BoxBoundedGeo> volumes;
569 if (entry_point >= 0) {
570 volumes = tpc_volumes.at(cryostat_index);
571 for (
unsigned i = 0; i < volumes.size(); i++) {
572 if (volumes[i].ContainsPosition(particle.Position(entry_point).Vect())) {
574 trueparticle.
cont_tpc = entry_point == 0;
578 trueparticle.
contained = entry_point == 0;
591 if (entry_point >= 0) {
593 const simb::MCTrajectory &trajectory = particle.Trajectory();
594 TVector3 pos = trajectory.Position(entry_point).Vect();
595 for (
unsigned i = entry_point+1; i < particle.NumberTrajectoryPoints(); i++) {
596 TVector3 this_point = trajectory.Position(i).Vect();
601 for (
unsigned j = 0; j < volumes.size(); j++) {
602 if (volumes[j].ContainsPosition(this_point) && tpc_index >= 0 && j != ((unsigned)tpc_index)) {
610 trueparticle.
cont_tpc = volumes[tpc_index].ContainsPosition(this_point);
614 trueparticle.
contained = active_volumes.at(cryostat_index).ContainsPosition(this_point);
617 trueparticle.
length += (this_point - pos).Mag();
619 if (!active_volumes.at(cryostat_index).ContainsPosition(this_point) && active_volumes.at(cryostat_index).ContainsPosition(pos)) {
623 pos = trajectory.Position(i).Vect();
626 if (exit_point < 0 && entry_point >= 0) {
627 exit_point = particle.NumberTrajectoryPoints() - 1;
629 if (exit_point >= 0 && ((
unsigned)exit_point) < particle.NumberTrajectoryPoints() - 1) {
630 trueparticle.
wallout = (int)
caf::GetWallCross(active_volumes.at(cryostat_index), particle.Position(exit_point).Vect(), particle.Position(exit_point+1).Vect());
634 trueparticle.
pdg = particle.PdgCode();
636 trueparticle.
gen =
ConvertTVector(particle.NumberTrajectoryPoints() ? particle.Position().Vect() : TVector3(-9999, -9999, -9999));
637 trueparticle.
genT = particle.NumberTrajectoryPoints() ? particle.Position().T() / 1000. : -9999;
638 trueparticle.
genp =
ConvertTVector(particle.NumberTrajectoryPoints() ? particle.Momentum().Vect(): TVector3(-9999, -9999, -9999));
639 trueparticle.
genE = particle.NumberTrajectoryPoints() ? particle.Momentum().E(): -9999;
641 trueparticle.
start =
ConvertTVector((entry_point >= 0) ? particle.Position(entry_point).Vect(): TVector3(-9999, -9999, -9999));
642 trueparticle.
startT = (entry_point >= 0) ? particle.Position(entry_point).T() / 1000. : -9999;
643 trueparticle.
end =
ConvertTVector((exit_point >= 0) ? particle.Position(exit_point).Vect(): TVector3(-9999, -9999, -9999));
644 trueparticle.
endT = (exit_point >= 0) ? particle.Position(exit_point).T() / 1000. : -9999;
646 trueparticle.
startp =
ConvertTVector((entry_point >= 0) ? particle.Momentum(entry_point).Vect() : TVector3(-9999, -9999, -9999));
647 trueparticle.
startE = (entry_point >= 0) ? particle.Momentum(entry_point).E() : -9999.;
648 trueparticle.
endp =
ConvertTVector((exit_point >= 0) ? particle.Momentum(exit_point).Vect() : TVector3(-9999, -9999, -9999));
649 trueparticle.
endE = (exit_point >= 0) ? particle.Momentum(exit_point).E() : -9999.;
654 trueparticle.
G4ID = particle.TrackId();
655 trueparticle.
parent = particle.Mother();
658 std::map<unsigned, sbn::TrueHit> truehits;
660 for (
auto const &ide_pair: particle_ides) {
663 const sim::IDE *ide = ide_pair.second;
667 truehits[c].tpc = w.
TPC;
668 truehits[c].plane = w.
Plane;
669 truehits[c].wire = w.
Wire;
670 truehits[c].channel = c;
673 float old_elec = truehits[c].nelec;
675 truehits[c].p.x = (truehits[c].p.x*old_elec + ide->
x*ide->
numElectrons) / new_elec;
676 truehits[c].p.y = (truehits[c].p.y*old_elec + ide->
y*ide->
numElectrons) / new_elec;
677 truehits[c].p.z = (truehits[c].p.z*old_elec + ide->
z*ide->
numElectrons) / new_elec;
683 truehits[c].p_scecorr.x = (truehits[c].p_scecorr.x*old_elec + ide_p_scecorr.x()*ide->
numElectrons) / new_elec;
684 truehits[c].p_scecorr.y = (truehits[c].p_scecorr.y*old_elec + ide_p_scecorr.y()*ide->
numElectrons) / new_elec;
685 truehits[c].p_scecorr.z = (truehits[c].p_scecorr.z*old_elec + ide_p_scecorr.z()*ide->
numElectrons) / new_elec;
689 truehits[c].e += ide->
energy;
690 truehits[c].ndep += 1;
694 for (
auto const &ide_pair: particle_ides) {
697 const sim::IDE *ide = ide_pair.second;
705 truehits[c].p_width.x += (ide_p.x() - truehits[c].p.x) * (ide_p.x() - truehits[c].p.x) * this_elec / truehits[c].nelec;
706 truehits[c].p_width.y += (ide_p.y() - truehits[c].p.y) * (ide_p.y() - truehits[c].p.y) * this_elec / truehits[c].nelec;
707 truehits[c].p_width.z += (ide_p.z() - truehits[c].p.z) * (ide_p.z() - truehits[c].p.z) * this_elec / truehits[c].nelec;
709 truehits[c].p_scecorr_width.x += (ide_p_scecorr.x() - truehits[c].p_scecorr.x) * (ide_p_scecorr.x() - truehits[c].p_scecorr.x) * this_elec / truehits[c].nelec;
710 truehits[c].p_scecorr_width.y += (ide_p_scecorr.y() - truehits[c].p_scecorr.y) * (ide_p_scecorr.y() - truehits[c].p_scecorr.y) * this_elec / truehits[c].nelec;
711 truehits[c].p_scecorr_width.z += (ide_p_scecorr.z() - truehits[c].p_scecorr.z) * (ide_p_scecorr.z() - truehits[c].p_scecorr.z) * this_elec / truehits[c].nelec;
715 std::vector<sbn::TrueHit> truehits_v;
716 for (
auto const &
p: truehits) {
717 truehits_v.push_back(
p.second);
731 TVector3 h_p(
h.p_scecorr.x,
h.p_scecorr.y,
h.p_scecorr.z);
734 float closest_dist = -1.;
736 for (
unsigned i_traj = 0; i_traj < particle.NumberTrajectoryPoints(); i_traj++) {
737 if (closest_dist < 0. || (particle.Position(i_traj).Vect() - h_p).Mag() < closest_dist) {
738 direction = particle.Momentum(i_traj).Vect().Unit();
739 closest_dist = (particle.Position(i_traj).Vect() - h_p).Mag();
745 if (closest_dist >= 0. && direction.Mag() > 1
e-4) {
748 float cosgamma =
abs(cos(angletovert) * direction.Z() + sin(angletovert) * direction.Y());
749 float pitch = geo->
WirePitch(plane) / cosgamma;
756 if (closest_dist >= 0. && direction.Mag() > 1
e-4) {
760 TVector3 loc_mdx_v = h_p - direction * (geo->
WirePitch(geo->
View(plane) / 2.));
761 TVector3 loc_pdx_v = h_p + direction * (geo->
WirePitch(geo->
View(plane) / 2.));
764 geo::Point_t loc_mdx(loc_mdx_v.X(), loc_mdx_v.Y(), loc_mdx_v.Z());
765 geo::Point_t loc_pdx(loc_pdx_v.X(), loc_pdx_v.Y(), loc_pdx_v.Z());
775 double cosgamma =
std::abs(std::sin(angletovert)*dir.Y() + std::cos(angletovert)*dir.Z());
790 h.pitch_sce = (locw_pdx_traj -
loc).R();
797 h.itraj = traj_index;
801 if (traj_index >= 0) {
802 for (
int i_traj = traj_index+1; i_traj < (int)particle.NumberTrajectoryPoints(); i_traj++) {
803 h.rr += (particle.Position(i_traj).Vect() - particle.Position(i_traj-1).Vect()).Mag();
807 double hit_distance_along_particle = (h_p - particle.Position(traj_index).Vect()).Dot(particle.Momentum(traj_index).Vect().Unit());
808 h.rr += -hit_distance_along_particle;
814 std::sort(truehits_v.begin(), truehits_v.end(),
815 [](
auto const &lhs,
auto const &rhs) {
816 return lhs.itraj < rhs.itraj;
824 else if (
h.plane == 1) {
827 else if (
h.plane == 2) {
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space.
int end_process
End G4 process of the particle. Values defined as enum in StandardRecord.
float z
z position of ionization [cm]
sbn::Vector3D ConvertTVector(const TVector3 &tv)
int wallout
Wall of cryostat particle exits (wNone if stopping in detector)
Vector3D endp
Momentum at last point in the active TPC volume [GeV/c].
Vector3D genp
Momentum at generation point [GeV/c].
Vector3D gen
Generation position [cm].
The data type to uniquely identify a Plane.
CryostatID_t Cryostat
Index of cryostat.
WireID_t Wire
Index of the wire within its plane.
std::vector< TrueHit > truehits0
List of True "hits" of this particle on Plane 0.
float x
x position of ionization [cm]
unsigned plane1nhit
Number of hits on plane 1 (2nd Ind.)
int wallin
Wall of cryostat particle enters (wNone if starting in detector)
geo::Length_t WirePitch(geo::PlaneID const &planeid) const
Returns the distance between two consecutive wires.
std::vector< TrueHit > truehits2
List of True "hits" of this particle on Plane 2.
float genE
Energy at generation pt [GeV].
geo::Point_t WireToTrajectoryPosition(const geo::Point_t &loc, const geo::TPCID &tpc)
unsigned plane0nhit
Number of hits on plane 0 (1st Ind.)
float plane2VisE
Sum of energy deposited on plane 2 (Col.) [GeV].
caf::g4_process_ GetG4ProcessID(const std::string &name)
Ionization at a point of the TPC sensitive volume.
bool contained
Whether the particle is contained in a single active volume.
float endT
End time last point in the active [mus – t=0 is spill time].
Vector3D start
Start position in the active TPC volume [cm].
bool crosses_tpc
Whether the particle crosses a TPC boundary.
bool cont_tpc
Whether the particle is contained in a single TPC.
float energy
energy deposited by ionization by this track ID and time [MeV]
std::vector< TrueHit > truehits1
List of True "hits" of this particle on Plane 1.
double ConvertXToTicks(double X, int p, int t, int c) const
geo::Point_t TrajectoryToWirePosition(const geo::Point_t &loc, const geo::TPCID &tpc)
double DriftVelocity(double efield=0., double temperature=0.) const
cm/us
PlaneID_t Plane
Index of the plane within its TPC.
View_t View(geo::PlaneID const &pid) const
Returns the view (wire orientation) on the channels of specified TPC plane.
float plane1VisE
Sum of energy deposited on plane 1 (2nd Ind.) [GeV].
float endE
Energy at last pt in active TPC volume [GeV].
Vector3D end
End position in the active TPC volume [cm].
float startT
Start time of first TPC point [mus – t=0 is spill time].
float y
y position of ionization [cm]
raw::ChannelID_t PlaneWireToChannel(WireID const &wireid) const
Returns the ID of the TPC channel connected to the specified wire.
float length
Trajectory length in active TPC volume the particle first enters [cm].
float startE
Energy at first pt in active TPC volume [GeV].
float plane0VisE
Sum of energy deposited on plane 0 (1st Ind.) [GeV].
float genT
Start time of gen point [mus – t=0 is spill time].
unsigned plane2nhit
Number of hits on plane 2 (Col.)
int G4ID
ID of the particle (taken from G4 – -1 if this particle is not propogated by G4)
TPCGeo const & TPC(unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified TPC.
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.
bool empty(FixedBins< T, C > const &) noexcept
int start_process
Start G4 process of the particle. Values defned as enum in StandardRecord.
const double * PlaneLocation(unsigned int p) const
double WireAngleToVertical(geo::View_t view, geo::TPCID const &tpcid) const
Returns the angle of the wires in the specified view from vertical.
int parent
ID of parent particle.
float numElectrons
number of electrons at the readout for this track ID and time
caf::Wall_t GetWallCross(const geo::BoxBoundedGeo &volume, const TVector3 p0, const TVector3 p1)
Vector3D startp
Momentum at first point in the active TPC volume [GeV/c].