All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Namespaces | Macros | Functions
FillTrue.cxx File Reference
#include "FillTrue.h"
#include "larcorealg/GeoAlgo/GeoAlgo.h"
#include "RecoUtils/RecoUtils.h"
#include <functional>
#include <algorithm>

Go to the source code of this file.

Namespaces

 caf
 Common Analysis Files.
 

Macros

#define MATCH_PROCESS(name)   if (process_name == #name) {return caf::kG4 ## name;}
 
#define MATCH_PROCESS_NAMED(strname, id)   if (process_name == #strname) {return caf::kG4 ## id;}
 

Functions

caf::SRTrackTruth MatchTrack2Truth (const detinfo::DetectorClocksData &clockData, const std::vector< caf::SRTrueParticle > &particles, const std::vector< art::Ptr< recob::Hit >> &hits, const std::map< int, caf::HitsEnergy > &all_hits_map)
 
caf::SRTruthMatch MatchSlice2Truth (const std::vector< art::Ptr< recob::Hit >> &hits, const std::vector< art::Ptr< simb::MCTruth >> &neutrinos, const caf::SRTruthBranch &srtruth, const cheat::ParticleInventoryService &inventory_service, const detinfo::DetectorClocksData &clockData)
 
float ContainedLength (const TVector3 &v0, const TVector3 &v1, const std::vector< geoalgo::AABox > &boxes)
 
bool FRFillNumuCC (const simb::MCTruth &mctruth, const std::vector< art::Ptr< sim::MCTrack >> &mctracks, const std::vector< geo::BoxBoundedGeo > &volumes, TRandom &rand, caf::SRFakeReco &fakereco)
 
bool FRFillNueCC (const simb::MCTruth &mctruth, const std::vector< caf::SRTrueParticle > &srparticle, const std::vector< geo::BoxBoundedGeo > &volumes, TRandom &rand, caf::SRFakeReco &fakereco)
 
bool isFromNuVertex (const simb::MCTruth &mc, const sim::MCTrack &track, float distance=5.0)
 
double PDGMass (int pdg)
 
double SmearLepton (const caf::SRTrueParticle &lepton, TRandom &rand)
 
double SmearHadron (const caf::SRTrueParticle &hadron, TRandom &rand)
 
void CopyTMatrixDToVector (const TMatrixD &m, std::vector< float > &v)
 
void caf::FillSRGlobal (const sbn::evwgh::EventWeightParameterSet &pset, caf::SRGlobal &srglobal, std::map< std::string, unsigned int > &weightPSetIndex)
 
void caf::FillTrackTruth (const std::vector< art::Ptr< recob::Hit >> &hits, const std::map< int, caf::HitsEnergy > &id_hits_map, const std::vector< caf::SRTrueParticle > &particles, const detinfo::DetectorClocksData &clockData, caf::SRTrack &srtrack, bool allowEmpty)
 
void caf::FillShowerTruth (const std::vector< art::Ptr< recob::Hit >> &hits, const std::map< int, caf::HitsEnergy > &id_hits_map, const std::vector< caf::SRTrueParticle > &particles, const detinfo::DetectorClocksData &clockData, caf::SRShower &srshower, bool allowEmpty)
 
void caf::FillStubTruth (const std::vector< art::Ptr< recob::Hit >> &hits, const std::map< int, caf::HitsEnergy > &id_hits_map, const std::vector< caf::SRTrueParticle > &particles, const detinfo::DetectorClocksData &clockData, caf::SRStub &srstub, bool allowEmpty)
 
void caf::FillSliceTruth (const std::vector< art::Ptr< recob::Hit >> &hits, const std::vector< art::Ptr< simb::MCTruth >> &neutrinos, const caf::SRTruthBranch &srmc, const cheat::ParticleInventoryService &inventory_service, const detinfo::DetectorClocksData &clockData, caf::SRSlice &srslice, bool allowEmpty)
 
void caf::FillMeVPrtlTruth (const evgen::ldm::MeVPrtlTruth &truth, const std::vector< geo::BoxBoundedGeo > &active_volumes, caf::SRMeVPrtl &srtruth)
 
void caf::FillSliceFakeReco (const std::vector< art::Ptr< recob::Hit >> &hits, const std::vector< art::Ptr< simb::MCTruth >> &neutrinos, const caf::SRTruthBranch &srmc, const cheat::ParticleInventoryService &inventory_service, const detinfo::DetectorClocksData &clockData, caf::SRSlice &srslice, const std::vector< caf::SRTrueParticle > &srparticles, const std::vector< art::Ptr< sim::MCTrack >> &mctracks, const std::vector< geo::BoxBoundedGeo > &volumes, TRandom &rand)
 
void caf::FillTrueNeutrino (const art::Ptr< simb::MCTruth > mctruth, const simb::MCFlux &mcflux, const simb::GTruth &gtruth, const std::vector< caf::SRTrueParticle > &srparticles, const std::map< int, std::vector< art::Ptr< recob::Hit >>> &id_to_truehit_map, caf::SRTrueInteraction &srneutrino, size_t i, const std::vector< geo::BoxBoundedGeo > &active_volumes)
 
void caf::FillEventWeight (const sbn::evwgh::EventWeightMap &wgtmap, caf::SRTrueInteraction &srint, const std::map< std::string, unsigned int > &weightPSetIndex)
 
void caf::FillTrueG4Particle (const simb::MCParticle &particle, const std::vector< geo::BoxBoundedGeo > &active_volumes, const std::vector< std::vector< geo::BoxBoundedGeo >> &tpc_volumes, const std::map< int, std::vector< std::pair< geo::WireID, const sim::IDE * >>> &id_to_ide_map, const std::map< int, std::vector< art::Ptr< recob::Hit >>> &id_to_truehit_map, const cheat::BackTrackerService &backtracker, const cheat::ParticleInventoryService &inventory_service, const std::vector< art::Ptr< simb::MCTruth >> &neutrinos, caf::SRTrueParticle &srparticle)
 
void caf::FillFakeReco (const std::vector< art::Ptr< simb::MCTruth >> &mctruths, const std::vector< caf::SRTrueParticle > &srparticles, const std::vector< art::Ptr< sim::MCTrack >> &mctracks, const std::vector< geo::BoxBoundedGeo > &volumes, TRandom &rand, std::vector< caf::SRFakeReco > &srfakereco)
 
std::map< int, caf::HitsEnergycaf::SetupIDHitEnergyMap (const std::vector< art::Ptr< recob::Hit >> &allHits, const detinfo::DetectorClocksData &clockData, const cheat::BackTrackerService &backtracker)
 
std::map< int, std::vector
< art::Ptr< recob::Hit > > > 
caf::PrepTrueHits (const std::vector< art::Ptr< recob::Hit >> &allHits, const detinfo::DetectorClocksData &clockData, const cheat::BackTrackerService &backtracker)
 
std::map< int, std::vector
< std::pair< geo::WireID,
const sim::IDE * > > > 
caf::PrepSimChannels (const std::vector< art::Ptr< sim::SimChannel >> &simchannels, const geo::GeometryCore &geo)
 

Macro Definition Documentation

#define MATCH_PROCESS (   name)    if (process_name == #name) {return caf::kG4 ## name;}
#define MATCH_PROCESS_NAMED (   strname,
  id 
)    if (process_name == #strname) {return caf::kG4 ## id;}

Function Documentation

float ContainedLength ( const TVector3 &  v0,
const TVector3 &  v1,
const std::vector< geoalgo::AABox > &  boxes 
)

Definition at line 1171 of file FillTrue.cxx.

1172  {
1173  static const geoalgo::GeoAlgo algo;
1174 
1175  // if points are the same, return 0
1176  if ((v0 - v1).Mag() < 1e-6) return 0;
1177 
1178  // construct individual points
1179  geoalgo::Point_t p0(v0);
1180  geoalgo::Point_t p1(v1);
1181 
1182  // construct line segment
1183  geoalgo::LineSegment line(p0, p1);
1184 
1185  double length = 0;
1186 
1187  // total contained length is sum of lengths in all boxes
1188  // assuming they are non-overlapping
1189  for (auto const &box: boxes) {
1190  int n_contained = box.Contain(p0) + box.Contain(p1);
1191  // both points contained -- length is total length (also can break out of loop)
1192  if (n_contained == 2) {
1193  length = (v1 - v0).Mag();
1194  break;
1195  }
1196  // one contained -- have to find intersection point (which must exist)
1197  if (n_contained == 1) {
1198  auto intersections = algo.Intersection(line, box);
1199  // Because of floating point errors, it can sometimes happen
1200  // that there is 1 contained point but no "Intersections"
1201  // if one of the points is right on the edge
1202  if (intersections.size() == 0) {
1203  // determine which point is on the edge
1204  double tol = 1e-5;
1205  bool p0_edge = algo.SqDist(p0, box) < tol;
1206  bool p1_edge = algo.SqDist(p1, box) < tol;
1207  assert(p0_edge || p1_edge);
1208  // contained one is on edge -- can treat both as not contained
1209  //
1210  // In this case, no length
1211  if ((p0_edge && box.Contain(p0)) || (box.Contain(p1) && p1_edge))
1212  continue;
1213  // un-contaned one is on edge -- treat both as contained
1214  else if ((p0_edge && box.Contain(p1)) || (box.Contain(p0) && p1_edge)) {
1215  length = (v1 - v0).Mag();
1216  break;
1217  }
1218  else {
1219  assert(false); // bad
1220  }
1221  }
1222  // floating point errors can also falsely cause 2 intersection points
1223  //
1224  // in this case, one of the intersections must be very close to the
1225  // "contained" point, so the total contained length will be about
1226  // the same as the distance between the two intersection points
1227  else if (intersections.size() == 2) {
1228  length += (intersections.at(0).ToTLorentzVector().Vect() - intersections.at(1).ToTLorentzVector().Vect()).Mag();
1229  continue;
1230  }
1231  // "Correct"/ideal case -- 1 intersection point
1232  else if (intersections.size() == 1) {
1233  // get TVector at intersection point
1234  TVector3 int_tv(intersections.at(0).ToTLorentzVector().Vect());
1235  length += ( box.Contain(p0) ? (v0 - int_tv).Mag() : (v1 - int_tv).Mag() );
1236  }
1237  else assert(false); // bad
1238  }
1239  // none contained -- either must have zero or two intersections
1240  if (n_contained == 0) {
1241  auto intersections = algo.Intersection(line, box);
1242  if (!(intersections.size() == 0 || intersections.size() == 2)) {
1243  // more floating point error fixes...
1244  //
1245  // figure out which points are near the edge
1246  double tol = 1e-5;
1247  bool p0_edge = algo.SqDist(p0, box) < tol;
1248  bool p1_edge = algo.SqDist(p1, box) < tol;
1249  // and which points are near the intersection
1250  TVector3 vint = intersections.at(0).ToTLorentzVector().Vect();
1251 
1252  bool p0_int = (v0 - vint).Mag() < tol;
1253  bool p1_int = (v1 - vint).Mag() < tol;
1254  // exactly one of them should produce the intersection
1255  assert((p0_int && p0_edge) != (p1_int && p1_edge));
1256  // void variables when assert-ions are turned off
1257  (void) p0_int; (void) p1_int;
1258 
1259  // both close to edge -- full length is contained
1260  if (p0_edge && p1_edge) {
1261  length += (v0 - v1).Mag();
1262  }
1263  // otherwise -- one of them is not on an edge, no length is contained
1264  else {}
1265  }
1266  // assert(intersections.size() == 0 || intersections.size() == 2);
1267  else if (intersections.size() == 2) {
1268  TVector3 start(intersections.at(0).ToTLorentzVector().Vect());
1269  TVector3 end(intersections.at(1).ToTLorentzVector().Vect());
1270  length += (start - end).Mag();
1271  }
1272  }
1273  }
1274 
1275  return length;
1276 }//ContainedLength
Algorithm to compute various geometrical relation among geometrical objects. In particular functions ...
auto const tol
Definition: SurfXYZTest.cc:16
double SqDist(const Line_t &line, const Point_t &pt) const
Representation of a simple 3D line segment Defines a finite 3D straight line by having the start and ...
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
j template void())
Definition: json.hpp:3108
do i e
std::vector< Point_t > Intersection(const AABox_t &box, const HalfLine_t &line, bool back=false) const
Intersection between a HalfLine and an AABox.
physics associatedGroupsWithLeft p1
void CopyTMatrixDToVector ( const TMatrixD &  m,
std::vector< float > &  v 
)

Definition at line 79 of file FillTrue.cxx.

80 {
81  const double& start = m(0, 0);
82  v.insert(v.end(), &start, &start + m.GetNoElements());
83 }
tuple m
now if test mode generate materials, CRT shell, world, gdml header else just generate CRT shell for u...
bool FRFillNueCC ( const simb::MCTruth &  mctruth,
const std::vector< caf::SRTrueParticle > &  srparticle,
const std::vector< geo::BoxBoundedGeo > &  volumes,
TRandom &  rand,
caf::SRFakeReco fakereco 
)

Definition at line 873 of file FillTrue.cxx.

877  {
878  // Configuration -- TODO: make configurable?
879 
880  // Fiducial Volume
881  float xmin = 10.;
882  float xmax = 10.;
883  float ymin = 10.;
884  float ymax = 10.;
885  float zmin = 10.;
886  float zmax = 100.;
887 
888  // energy smearing
889 /* auto smear_lepton = [&rand](const caf::SRTrueParticle &lepton) -> float {
890  const double smearing = 0.15;
891  // Oscillation tech note says smear ionization deposition, but
892  // code in old samples seems to use true energy.
893  const double true_E = lepton.plane[0][2].visE + lepton.plane[1][2].visE;
894  const double smeared_E = rand.Gaus(true_E, smearing * true_E / std::sqrt(true_E));
895  return std::max(smeared_E, 0.0);
896  };
897  auto smear_hadron = [&rand](const caf::SRTrueParticle &hadron) -> float {
898  const double smearing = 0.05;
899  const double true_E = hadron.startE - PDGMass(hadron.pdg) / 1000;
900  const double smeared_E = rand.Gaus(true_E, smearing * true_E);
901  return std::max(smeared_E, 0.0);
902  };
903 */
904  // visible energy threshold
905  const float hadronic_energy_threshold = 0.021; // GeV
906 
907  fakereco.filled = false;
908 
909  // first check if neutrino exists
910  if (!mctruth.NeutrinoSet()) return false;
911 
912  TVector3 nuVtx = mctruth.GetNeutrino().Nu().Position().Vect();
913 
914  // then check if fiducial
915  int cryo_index = -1;
916  for (unsigned i = 0; i < volumes.size(); i++) {
917  const geo::BoxBoundedGeo &vol = volumes[i];
918  geo::BoxBoundedGeo FV(vol.MinX() + xmin, vol.MaxX() - xmax, vol.MinY() + ymin, vol.MaxY() - ymax, vol.MinZ() + zmin, vol.MaxZ() - zmax);
919  if (FV.ContainsPosition(nuVtx)) {
920  cryo_index = i;
921  break;
922  }
923  }
924 
925  if (cryo_index == -1) return false;
926 
927  std::vector<geoalgo::AABox> aa_volumes;
928  const geo::BoxBoundedGeo &v = volumes.at(cryo_index);
929  aa_volumes.emplace_back(v.MinX(), v.MinY(), v.MinZ(), v.MaxX(), v.MaxY(), v.MaxZ());
930 
931  //Showers arising from the vertex are identified and the reconstructed energy is found
932  //from smearing the ionisation deposition. If more than one shower with energy above
933  //100 MeV exists, the event is removed. This removes neutral pion events where the
934  //pion decays into two photon showers.
935 
936  std::vector<const caf::SRTrueParticle*> lepton_candidates;
937  for(const auto& particle: srparticles) {
938  const int pdg = std::abs(particle.pdg);
939  const float distance_from_vertex = std::hypot(nuVtx.X() - particle.start.x,
940  nuVtx.Y() - particle.start.y,
941  nuVtx.Z() - particle.start.z);
942  if((pdg == 11 || pdg == 22) && distance_from_vertex < 5) {
943  const auto parent = std::find_if(srparticles.begin(), srparticles.end(),
944  [&particle](const caf::SRTrueParticle& parent_candidate) -> bool {
945  return particle.parent == std::abs(parent_candidate.G4ID);
946  });
947  if((parent == srparticles.end()
948  || !(std::abs((*parent).pdg) == 11 || std::abs((*parent).pdg) == 22))
949  && SmearLepton(particle, rand) > 0.1) {
950  lepton_candidates.push_back(&particle);
951  }
952  }
953  }
954  if(lepton_candidates.size() != 1) return false;
955 
956  const caf::SRTrueParticle* lepton = lepton_candidates[0];
957  caf::SRFakeRecoParticle fake_lepton;
958  fake_lepton.pid = 11;
959  fake_lepton.ke = SmearLepton(*lepton, rand) - PDGMass(11) / 1000;
960  // Should these be set for a shower?
961  // fake_lepton.len = ???;
962  // fake_lepton.costh = ???;
963  // fake_lepton.contained = false;
964 
965  // Get hadrons
966 
967  std::vector<caf::SRFakeRecoParticle> fake_hadrons;
968  float hadronic_E = 0.0;
969  for(const auto& particle: srparticles) {
970  const int pdg = std::abs(particle.pdg);
971  const float ke = SmearHadron(particle, rand);
972  const float distance_from_vertex = std::hypot(nuVtx.X() - particle.start.x,
973  nuVtx.Y() - particle.start.y,
974  nuVtx.Z() - particle.start.z);
975 
976  if((pdg == 2212 || pdg == 211 || pdg == 321) && distance_from_vertex < 5
977  && particle.start_process == caf::kG4primary && ke > hadronic_energy_threshold) {
978  caf::SRFakeRecoParticle fake_hadron;
979  fake_hadron.pid = pdg;
980  fake_hadron.len = ContainedLength(TVector3(particle.start), TVector3(particle.end), aa_volumes);
981  fake_hadron.contained = false;
982  for(const geo::BoxBoundedGeo &vol: volumes) {
983  if(vol.ContainsPosition(TVector3(particle.start))
984  && vol.ContainsPosition(TVector3(particle.end))) {
985  fake_hadron.contained = true;
986  }
987  }
988  fake_hadron.costh = TVector3(particle.start).CosTheta();
989  fake_hadron.ke = ke;
990  hadronic_E += ke;
991  fake_hadrons.push_back(fake_hadron);
992  }
993  }
994 
995  // If there is only one photon candidate in the event, a conversion gap cut is applied.
996  // If the vertex is deemed visible, due to the presence of at least 50 MeV of hadronic
997  // kinetic energy, and the photon starts to shower further than 3 cm from the vertex the
998  // event is removed.
999 
1000  if(lepton->pdg == 22 && hadronic_E > 0.05 && (TVector3(lepton->end) - nuVtx).Mag() > 3)
1001  return false;
1002 
1003  // Remaining photons undergo a dE/dx cut resulting in a 94% background rejection.
1004 
1005  double weight = 1.0;
1006  if(lepton->pdg == 22) weight *= 0.06;
1007 
1008  // If a misidentified photon originates from a resonant numuCC interaction, the muon
1009  // lepton is identified. Events where a muon travels greater than 1 m are assumed to be
1010  // from numuCC interactions and the event is removed.
1011 
1012  if(std::abs(mctruth.GetNeutrino().Nu().PdgCode()) == 14 && mctruth.GetNeutrino().CCNC() == 0) {
1013  const caf::SRTrueParticle* muon = NULL;
1014  for(const auto& particle: srparticles) {
1015  const int pdg = std::abs(particle.pdg);
1016  const float distance_from_vertex = std::hypot(nuVtx.X() - particle.start.x,
1017  nuVtx.Y() - particle.start.y,
1018  nuVtx.Z() - particle.start.z);
1019  if(pdg == 13 && distance_from_vertex < 5 && particle.start_process == caf::kG4primary
1020  && (muon == NULL || muon->startE < particle.startE))
1021  muon = &particle;
1022  }
1023  if(muon != NULL && ContainedLength(TVector3(muon->start), TVector3(muon->end), aa_volumes) > 100)
1024  return false;
1025  }
1026 
1027  // Events where the shower has an energy less than 200 MeV are removed
1028 
1029  if((lepton->plane[0][2].visE + lepton->plane[1][2].visE) < 0.2) return false;
1030 
1031  // total up the energy to get the reco neutrino energy
1032  fakereco.nuE = fake_lepton.ke + PDGMass(11) / 1000 + hadronic_E;
1033 
1034  // save the particles
1035  fakereco.lepton = fake_lepton;
1036  fakereco.hadrons = fake_hadrons;
1037 
1038  // other info
1039  fakereco.vtx.x = nuVtx.X();
1040  fakereco.vtx.y = nuVtx.Y();
1041  fakereco.vtx.z = nuVtx.Z();
1042 
1043  fakereco.wgt = 0.8;
1044  fakereco.wgt *= weight;
1045 
1046  fakereco.nhad = fakereco.hadrons.size();
1047  fakereco.filled = true;
1048 
1049  return true;
1050 }
double SmearHadron(const caf::SRTrueParticle &hadron, TRandom &rand)
Definition: FillTrue.cxx:70
double PDGMass(int pdg)
Definition: FillTrue.cxx:44
double ContainedLength(const TVector3 &v0, const TVector3 &v1, const std::vector< geo::BoxBoundedGeo > &boxes)
Definition: Interaction.cxx:28
var pdg
Definition: selectors.fcl:14
SRVector3D start
Start position in the active TPC volume [cm].
bool contained
Whether contained.
double MinX() const
Returns the world x coordinate of the start of the box.
Definition: BoxBoundedGeo.h:88
float ke
Fake-reco kinetic energy [GeV].
double SmearLepton(const caf::SRTrueParticle &lepton, TRandom &rand)
Definition: FillTrue.cxx:61
float len
Fake-reco particle length [cm].
double MaxX() const
Returns the world x coordinate of the end of the box.
Definition: BoxBoundedGeo.h:91
The SRFakeRecoParticle is a faked reconstruction using estimates from the SBN proposal.
process_name pandoraGausCryo1 vertexChargeCryo1 vertexStubCryo1 xmin
T abs(T value)
int pid
Fake-reco particle ID.
int nhad
Number of hadrons.
Definition: SRFakeReco.h:25
float nuE
Fake-reco neutrino Energy [GeV].
Definition: SRFakeReco.h:21
double MinZ() const
Returns the world z coordinate of the start of the box.
float costh
Fake-reco cosine of angle w.r.t. beam direction.
float wgt
Weight for this interaction.
Definition: SRFakeReco.h:26
double MaxY() const
Returns the world y coordinate of the end of the box.
std::vector< SRFakeRecoParticle > hadrons
Fake-reco information on hadronic state.
Definition: SRFakeReco.h:24
SRVector3D end
End position in the active TPC volume [cm].
float startE
Energy at first pt in active TPC volume [GeV].
process_name can override from command line with o or output muon
Definition: runPID.fcl:28
A base class aware of world box coordinatesAn object describing a simple shape can inherit from this ...
Definition: BoxBoundedGeo.h:33
double MaxZ() const
Returns the world z coordinate of the end of the box.
Representation of a simb::MCParticle, knows energy, direction,.
SRVector3D vtx
Interaction vertex in detector coordinates [cm].
Definition: SRFakeReco.h:22
SRFakeRecoParticle lepton
Fake-reco lepton information.
Definition: SRFakeReco.h:23
int pdg
Particle ID code.
double MinY() const
Returns the world y coordinate of the start of the box.
bool ContainsPosition(geo::Point_t const &point, double wiggle=1.0) const
Returns whether this volume contains the specified point.
SRTrueParticlePlaneInfo plane[2][3]
Per-plane, per-cryostat deposition information.
float visE
Sum of energy deposited on plane [GeV].
bool FRFillNumuCC ( const simb::MCTruth &  mctruth,
const std::vector< art::Ptr< sim::MCTrack >> &  mctracks,
const std::vector< geo::BoxBoundedGeo > &  volumes,
TRandom &  rand,
caf::SRFakeReco fakereco 
)

Definition at line 710 of file FillTrue.cxx.

714  {
715  // Configuration -- TODO: make configurable?
716 
717  // Fiducial Volume
718  float xmin = 10.;
719  float xmax = 10.;
720  float ymin = 10.;
721  float ymax = 10.;
722  float zmin = 10.;
723  float zmax = 100.;
724 
725  // energy smearing
726  float hadron_smearing = 0.05;
727  float lepton_contained_smearing = 0.02;
728  std::function<float (float)> lepton_exiting_smearing = [](float length) {
729  float A = 0.102;
730  float B = 0.000612;
731  return -A * TMath::Log(B * length);
732  };
733 
734  // visible energy threshold
735  float hadronic_energy_threshold = 0.021; // GeV
736 
737  // length cut
738  float contained_length_cut = 50.; // cm
739  float exiting_length_cut = 100.; // cm
740 
741  fakereco.filled = false;
742 
743  // first check if neutrino exists
744  if (!mctruth.NeutrinoSet()) return false;
745 
746  // then check if fiducial
747  int cryo_index = -1;
748  for (unsigned i = 0; i < volumes.size(); i++) {
749  const geo::BoxBoundedGeo &vol = volumes[i];
750  geo::BoxBoundedGeo FV(vol.MinX() + xmin, vol.MaxX() - xmax, vol.MinY() + ymin, vol.MaxY() - ymax, vol.MinZ() + zmin, vol.MaxZ() - zmax);
751  if (FV.ContainsPosition(mctruth.GetNeutrino().Nu().Position().Vect())) {
752  cryo_index = i;
753  break;
754  }
755  }
756 
757  if (cryo_index == -1) return false;
758 
759  std::vector<geoalgo::AABox> aa_volumes;
760  const geo::BoxBoundedGeo &v = volumes.at(cryo_index);
761  aa_volumes.emplace_back(v.MinX(), v.MinY(), v.MinZ(), v.MaxX(), v.MaxY(), v.MaxZ());
762 
763  // look for CC lepton or a \pi^+/- which can "fake" a numu CC interaction
764 
765  int lepton_ind = -1;
766  // CC lepton
767  if (abs(mctruth.GetNeutrino().Nu().PdgCode()) == 14 && mctruth.GetNeutrino().CCNC() == 0) {
768  for (int i = 0; i < (int)mctracks.size(); i++) {
769  if (isFromNuVertex(mctruth, *mctracks[i]) && abs(mctracks[i]->PdgCode()) == 13 && mctracks[i]->Process() == "primary") {
770  if (lepton_ind == -1 || mctracks[lepton_ind]->Start().E() < mctracks[i]->Start().E()) {
771  lepton_ind = i;
772  }
773  }
774  }
775  }
776  // NC pion
777  else if (mctruth.GetNeutrino().CCNC() == 1) {
778  for (int i = 0; i < (int)mctracks.size(); i++) {
779  if (isFromNuVertex(mctruth, *mctracks[i]) && abs(mctracks[i]->PdgCode()) == 211 && mctracks[i]->Process() == "primary") {
780  if (lepton_ind == -1 || mctracks[lepton_ind]->Start().E() < mctracks[i]->Start().E()) {
781  lepton_ind = i;
782  }
783  }
784  }
785  }
786 
787  // no matching track -- no fake reco
788  if (lepton_ind == -1) return false;
789 
790  // Now set the "lepton"
791  caf::SRFakeRecoParticle fake_lepton;
792 
793  fake_lepton.pid = 13;
794  fake_lepton.contained = false;
795  for (const geo::BoxBoundedGeo &vol: volumes) {
796  if (vol.ContainsPosition(mctracks[lepton_ind]->Start().Position().Vect()) && vol.ContainsPosition(mctracks[lepton_ind]->Start().Position().Vect())) {
797  fake_lepton.contained = true;
798  }
799  }
800  fake_lepton.len = ContainedLength(mctracks[lepton_ind]->Start().Position().Vect(), mctracks[lepton_ind]->End().Position().Vect(), aa_volumes);
801  fake_lepton.costh = mctracks[lepton_ind]->Start().Position().Vect().CosTheta();
802 
803  // apply length cut
804  if (fake_lepton.contained && fake_lepton.len < contained_length_cut) return false;
805  if (!fake_lepton.contained && fake_lepton.len < exiting_length_cut) return false;
806 
807 
808  // smear the lepton energy
809  float smearing = fake_lepton.contained ? lepton_contained_smearing : lepton_exiting_smearing(fake_lepton.len);
810  float ke = (mctracks[lepton_ind]->Start().E() - PDGMass(mctracks[lepton_ind]->PdgCode())) / 1000. /* MeV -> GeV*/;
811  fake_lepton.ke = rand.Gaus(ke, smearing * ke);
812  fake_lepton.ke = std::max(fake_lepton.ke, 0.f);
813 
814  // get the hadronic state
815  std::vector<caf::SRFakeRecoParticle> hadrons;
816 
817  for (int i = 0; i < (int)mctracks.size(); i++) {
818  if (isFromNuVertex(mctruth, *mctracks[i]) // from this interaction
819  && (abs(mctracks[i]->PdgCode()) == 211 || abs(mctracks[i]->PdgCode()) == 321 || abs(mctracks[i]->PdgCode()) == 2212) // hadronic
820  && mctracks[i]->Process() == "primary" // primary
821  && i != lepton_ind // not the fake lepton
822  ) {
824  hadron.pid = abs(mctracks[i]->PdgCode());
825  hadron.contained = false;
826  for (const geo::BoxBoundedGeo &vol: volumes) {
827  if (vol.ContainsPosition(mctracks[i]->Start().Position().Vect()) && vol.ContainsPosition(mctracks[i]->Start().Position().Vect())) {
828  hadron.contained = true;
829  }
830  }
831  hadron.len = ContainedLength(mctracks[i]->Start().Position().Vect(), mctracks[i]->Start().Position().Vect(), aa_volumes);
832  hadron.costh = mctracks[i]->Start().Position().Vect().CosTheta();
833 
834  float ke = (mctracks[i]->Start().E() - PDGMass(mctracks[i]->PdgCode())) / 1000. /* MeV -> GeV*/;
835  if (ke < hadronic_energy_threshold) continue;
836 
837  hadron.ke = rand.Gaus(ke, hadron_smearing * ke);
838  hadron.ke = std::max(hadron.ke, 0.f);
839 
840  hadrons.push_back(hadron);
841  }
842  }
843 
844  // total up the energy to get the reco neutrino energy
845  fakereco.nuE = fake_lepton.ke;
846  for (const caf::SRFakeRecoParticle &had: hadrons) fakereco.nuE += had.ke;
847  fakereco.nuE += PDGMass(13) / 1000.; // MeV -.> GeV
848 
849  // save the particles
850  fakereco.lepton = fake_lepton;
851  fakereco.hadrons = hadrons;
852 
853  // other info
854  TVector3 vertex = mctruth.GetNeutrino().Nu().Position().Vect();
855  fakereco.vtx.x = vertex.X();
856  fakereco.vtx.y = vertex.Y();
857  fakereco.vtx.z = vertex.Z();
858 
859  // signal
860  if (abs(mctruth.GetNeutrino().Nu().PdgCode()) == 14 && mctruth.GetNeutrino().CCNC() == 0) {
861  fakereco.wgt = 0.8;
862  }
863  // bkg
864  else {
865  fakereco.wgt = 1.;
866  }
867  fakereco.nhad = fakereco.hadrons.size();
868  fakereco.filled = true;
869 
870  return true;
871 }
process_name vertex
Definition: cheaterreco.fcl:51
double PDGMass(int pdg)
Definition: FillTrue.cxx:44
double ContainedLength(const TVector3 &v0, const TVector3 &v1, const std::vector< geo::BoxBoundedGeo > &boxes)
Definition: Interaction.cxx:28
bool contained
Whether contained.
double MinX() const
Returns the world x coordinate of the start of the box.
Definition: BoxBoundedGeo.h:88
float ke
Fake-reco kinetic energy [GeV].
float len
Fake-reco particle length [cm].
double MaxX() const
Returns the world x coordinate of the end of the box.
Definition: BoxBoundedGeo.h:91
The SRFakeRecoParticle is a faked reconstruction using estimates from the SBN proposal.
bool isFromNuVertex(const simb::MCTruth &mc, const sim::MCTrack &track, float distance=5.0)
Definition: FillTrue.cxx:36
process_name pandoraGausCryo1 vertexChargeCryo1 vertexStubCryo1 xmin
T abs(T value)
int pid
Fake-reco particle ID.
int nhad
Number of hadrons.
Definition: SRFakeReco.h:25
float nuE
Fake-reco neutrino Energy [GeV].
Definition: SRFakeReco.h:21
double MinZ() const
Returns the world z coordinate of the start of the box.
float costh
Fake-reco cosine of angle w.r.t. beam direction.
float wgt
Weight for this interaction.
Definition: SRFakeReco.h:26
double MaxY() const
Returns the world y coordinate of the end of the box.
std::vector< SRFakeRecoParticle > hadrons
Fake-reco information on hadronic state.
Definition: SRFakeReco.h:24
A base class aware of world box coordinatesAn object describing a simple shape can inherit from this ...
Definition: BoxBoundedGeo.h:33
double MaxZ() const
Returns the world z coordinate of the end of the box.
SRVector3D vtx
Interaction vertex in detector coordinates [cm].
Definition: SRFakeReco.h:22
float A
Definition: dedx.py:137
SRFakeRecoParticle lepton
Fake-reco lepton information.
Definition: SRFakeReco.h:23
double MinY() const
Returns the world y coordinate of the start of the box.
bool ContainsPosition(geo::Point_t const &point, double wiggle=1.0) const
Returns whether this volume contains the specified point.
bool isFromNuVertex ( const simb::MCTruth &  mc,
const sim::MCTrack track,
float  distance = 5.0 
)

Definition at line 36 of file FillTrue.cxx.

37  {
38  TVector3 nuVtx = mc.GetNeutrino().Nu().Trajectory().Position(0).Vect();
39  TVector3 trkStart = track.Start().Position().Vect();
40  return (trkStart - nuVtx).Mag() < distance;
41 }
double distance(geo::Point_t const &point, CathodeDesc_t const &cathode)
Returns the distance of a point from the cathode.
const MCStep & Start() const
Definition: MCTrack.h:44
const TLorentzVector & Position() const
Definition: MCStep.h:40
caf::SRTruthMatch MatchSlice2Truth ( const std::vector< art::Ptr< recob::Hit >> &  hits,
const std::vector< art::Ptr< simb::MCTruth >> &  neutrinos,
const caf::SRTruthBranch srtruth,
const cheat::ParticleInventoryService inventory_service,
const detinfo::DetectorClocksData clockData 
)

Definition at line 1367 of file FillTrue.cxx.

1371  {
1372  caf::SRTruthMatch ret;
1373  float total_energy = CAFRecoUtils::TotalHitEnergy(clockData, hits);
1374  // speed optimization: if there are no truths, all the matching energy must be cosmic
1375  if (truths.empty()) {
1376  ret.visEinslc = total_energy / 1000. /* MeV -> GeV */;
1377  ret.visEcosmic = total_energy / 1000. /* MeV -> GeV */;
1378  ret.eff_cryo = -1.;
1379  ret.eff = -1;
1380  ret.pur = -1;
1381  ret.index = -1;
1382  return ret;
1383  }
1384  std::vector<std::pair<int, float>> matches = CAFRecoUtils::AllTrueParticleIDEnergyMatches(clockData, hits, true);
1385  std::vector<float> matching_energy(truths.size(), 0.);
1386  for (auto const &pair: matches) {
1387  art::Ptr<simb::MCTruth> truth;
1388  try {
1389  truth = inventory_service.TrackIdToMCTruth_P(pair.first);
1390  }
1391  // Ignore track ID's that cannot be looked up
1392  catch(...) {
1393  continue;
1394  }
1395  for (unsigned ind = 0; ind < truths.size(); ind++) {
1396  if (truth == truths[ind]) {
1397  matching_energy[ind] += pair.second;
1398  break;
1399  }
1400  }
1401  }
1402 
1403  float cosmic_energy = total_energy;
1404  for (float E: matching_energy) cosmic_energy -= E;
1405 
1406  float matching_frac = *std::max_element(matching_energy.begin(), matching_energy.end()) / total_energy;
1407  int index = (matching_frac > 0.5) ? std::distance(matching_energy.begin(), std::max_element(matching_energy.begin(), matching_energy.end())) : -1;
1408 
1409  ret.index = index;
1410  if (index >= 0) {
1411  ret.visEinslc = total_energy / 1000. /* MeV -> GeV */;
1412  ret.visEcosmic = cosmic_energy / 1000. /* MeV -> GeV */;
1413  ret.pur = matching_energy[index] / total_energy;
1414 
1415  double totVisE = 0.;
1416  for (int p = 0; p < 3; p++) {
1417  for (int c = 0; c < 2; c++) {
1418  totVisE += srmc.nu[index].plane[c][p].visE;
1419  }
1420  }
1421 
1422  ret.eff = (matching_energy[index] / 1000.) / totVisE;
1423 
1424  // Lookup the cryostat
1425  int icryo = -1;
1426  if (!hits.empty()) {
1427  icryo = hits[0]->WireID().Cryostat;
1428  }
1429 
1430  if (icryo >= 0) {
1431  ret.eff_cryo = (matching_energy[index] / 1000.) /
1432  (srmc.nu[index].plane[icryo][0].visE + srmc.nu[index].plane[icryo][1].visE + srmc.nu[index].plane[icryo][2].visE);
1433  }
1434  else {
1435  ret.eff_cryo = -1;
1436  }
1437 
1438  }
1439  else {
1440  ret.pur = -1;
1441  ret.eff = -1;
1442  ret.eff_cryo = -1;
1443  }
1444  return ret;
1445 }//Slc2Truth
pdgs p
Definition: selectors.fcl:22
An SRTruthMatch contains overarching information for a slice.
Definition: SRTruthMatch.h:15
float eff
Slice efficiency for this interaction.
Definition: SRTruthMatch.h:22
process_name E
float visEinslc
True deposited energy in slice [GeV].
Definition: SRTruthMatch.h:25
float eff_cryo
Slice efficiency for this interaction for energy in the slice&#39;s cryostat.
Definition: SRTruthMatch.h:23
std::vector< std::pair< int, float > > AllTrueParticleIDEnergyMatches(const detinfo::DetectorClocksData &clockData, const std::vector< art::Ptr< recob::Hit > > &hits, bool rollup_unsaved_ids=1)
double distance(geo::Point_t const &point, CathodeDesc_t const &cathode)
Returns the distance of a point from the cathode.
const art::Ptr< simb::MCTruth > & TrackIdToMCTruth_P(int id) const
float pur
Slice purity for this interaction.
Definition: SRTruthMatch.h:24
int index
Index of the matched true neutrino interaction (-1 if not matched to neutrino)
Definition: SRTruthMatch.h:27
float TotalHitEnergy(const detinfo::DetectorClocksData &clockData, const std::vector< art::Ptr< recob::Hit > > &hits)
float visEcosmic
True slice deposited energy from cosmics.
Definition: SRTruthMatch.h:26
caf::SRTrackTruth MatchTrack2Truth ( const detinfo::DetectorClocksData clockData,
const std::vector< caf::SRTrueParticle > &  particles,
const std::vector< art::Ptr< recob::Hit >> &  hits,
const std::map< int, caf::HitsEnergy > &  all_hits_map 
)

Definition at line 1279 of file FillTrue.cxx.

1280  {
1281 
1282  art::ServiceHandle<cheat::BackTrackerService> bt_serv;
1283 
1284  // this id is the same as the mcparticle ID as long as we got it from geant4
1285  std::vector<std::pair<int, float>> matches = CAFRecoUtils::AllTrueParticleIDEnergyMatches(clockData, hits, true);
1286  float total_energy = CAFRecoUtils::TotalHitEnergy(clockData, hits);
1287  std::map<int, caf::HitsEnergy> track_hits_map = caf::SetupIDHitEnergyMap(hits, clockData, *bt_serv.get());
1288 
1289  caf::SRTrackTruth ret;
1290 
1291  ret.visEintrk = total_energy / 1000. /* MeV -> GeV */;
1292 
1293  // setup the matches
1294  for (auto const &pair: matches) {
1295  caf::SRParticleMatch match;
1296  match.G4ID = pair.first;
1297  match.energy = pair.second / 1000. /* MeV -> GeV */;
1298 
1299  caf::HitsEnergy track_matched_hits = track_hits_map.find(match.G4ID)->second;
1300  caf::HitsEnergy all_matched_hits = all_hits_map.find(match.G4ID)->second;
1301 
1302  match.hit_purity = (hits.size() != 0) ? track_matched_hits.nHits / (float) hits.size() : 0.;
1303  match.energy_purity = (ret.visEintrk > 0) ? match.energy / ret.visEintrk : 0.;
1304  match.hit_completeness = (all_matched_hits.nHits != 0) ? track_matched_hits.nHits / (float) all_matched_hits.nHits : 0.;
1305  match.energy_completeness = (all_matched_hits.totE > 0) ? pair.second / all_matched_hits.totE : 0.;
1306 
1307  ret.matches.push_back(match);
1308  }
1309 
1310  // sort highest energy match to lowest
1311  std::sort(ret.matches.begin(), ret.matches.end(),
1312  [](const caf::SRParticleMatch &a, const caf::SRParticleMatch &b) {
1313  return a.energy > b.energy;
1314  }
1315  );
1316 
1317  bool found_bestmatch = false;
1318  if (ret.matches.size()) {
1319  ret.bestmatch = ret.matches.at(0);
1320  for (unsigned i_part = 0; i_part < particles.size(); i_part++) {
1321  if (particles[i_part].G4ID == ret.bestmatch.G4ID) {
1322  ret.p = particles[i_part];
1323  found_bestmatch = true;
1324  break;
1325  }
1326  }
1327  }
1328 
1329  // Calculate efficiency / purity
1330  if (found_bestmatch) {
1331  double match_total_energy = 0.;
1332  for (int p = 0; p < 3; p++) {
1333  for (int c = 0; c < 2; c++) {
1334  match_total_energy += ret.p.plane[c][p].visE;
1335  }
1336  }
1337 
1338  ret.eff = ret.matches[0].energy / match_total_energy;
1339  ret.pur = ret.matches[0].energy / ret.visEintrk;
1340 
1341  int icryo = -1;
1342  if (!hits.empty()) {
1343  icryo = hits[0]->WireID().Cryostat;
1344  }
1345 
1346  assert(icryo < 2);
1347  if (icryo >= 0 && icryo < 2) {
1348  float match_cryo_energy = ret.p.plane[icryo][0].visE + ret.p.plane[icryo][1].visE + ret.p.plane[icryo][2].visE;
1349  ret.eff_cryo = ret.matches[0].energy / match_cryo_energy;
1350  }
1351  else {
1352  ret.eff_cryo = -1;
1353  }
1354 
1355  }
1356  else {
1357  ret.eff = -1.;
1358  ret.pur = -1.;
1359  ret.eff_cryo = -1.;
1360  }
1361 
1362  ret.nmatches = ret.matches.size();
1363 
1364  return ret;
1365 }//MatchTrack2Truth
pdgs p
Definition: selectors.fcl:22
float visEintrk
True total deposited energy associated with this Track across all 3 planes [GeV]. NOTE: this energy i...
Definition: SRTrackTruth.h:22
float hit_completeness
The fraction of the best true particle&#39;s hits contained by the reconstructed object.
float energy
Total energy matching between reco track and true particle across all three planes [GeV]...
std::map< int, caf::HitsEnergy > SetupIDHitEnergyMap(const std::vector< art::Ptr< recob::Hit >> &allHits, const detinfo::DetectorClocksData &clockData, const cheat::BackTrackerService &backtracker)
Definition: FillTrue.cxx:657
process_name gaushit a
std::vector< std::pair< int, float > > AllTrueParticleIDEnergyMatches(const detinfo::DetectorClocksData &clockData, const std::vector< art::Ptr< recob::Hit > > &hits, bool rollup_unsaved_ids=1)
float energy_purity
The fraction of the reconstructed object&#39;s energy that originates from the best true particle...
int G4ID
ID of the particle match, taken from G4 */.
float hit_purity
The fraction of the reconstructed object&#39;s hits that originate from the best true particle...
float TotalHitEnergy(const detinfo::DetectorClocksData &clockData, const std::vector< art::Ptr< recob::Hit > > &hits)
float energy_completeness
The fraction of the best true particle&#39;s energy contained by the reconstructed object.
Match from a reconstructed track to a true particle */.
double PDGMass ( int  pdg)

Definition at line 44 of file FillTrue.cxx.

44  {
45  const TDatabasePDG *PDGTable = TDatabasePDG::Instance();
46  // regular particle
47  if (pdg < 1000000000) {
48  TParticlePDG* ple = PDGTable->GetParticle(pdg);
49  if (ple == NULL) return -1;
50  return ple->Mass() * 1000.0;
51  }
52  // ion
53  else {
54  int p = (pdg % 10000000) / 10000;
55  int n = (pdg % 10000) / 10 - p;
56  return (PDGTable->GetParticle(2212)->Mass() * p +
57  PDGTable->GetParticle(2112)->Mass() * n) * 1000.0;
58  }
59 }
var pdg
Definition: selectors.fcl:14
pdgs p
Definition: selectors.fcl:22
static const TDatabasePDG * PDGTable(new TDatabasePDG)
double SmearHadron ( const caf::SRTrueParticle hadron,
TRandom &  rand 
)

Definition at line 70 of file FillTrue.cxx.

70  {
71  const double smearing = 0.05;
72  const double true_E = hadron.startE - PDGMass(hadron.pdg) / 1000;
73  const double smeared_E = rand.Gaus(true_E, smearing * true_E);
74  return std::max(smeared_E, 0.0);
75 }
double PDGMass(int pdg)
Definition: FillTrue.cxx:44
float startE
Energy at first pt in active TPC volume [GeV].
int pdg
Particle ID code.
double SmearLepton ( const caf::SRTrueParticle lepton,
TRandom &  rand 
)

Definition at line 61 of file FillTrue.cxx.

61  {
62  const double smearing = 0.15;
63  // Oscillation tech note says smear ionization deposition, but
64  // code in old samples seems to use true energy.
65  const double true_E = lepton.plane[0][2].visE + lepton.plane[1][2].visE;
66  const double smeared_E = rand.Gaus(true_E, smearing * true_E / std::sqrt(true_E));
67  return std::max(smeared_E, 0.0);
68 }
SRTrueParticlePlaneInfo plane[2][3]
Per-plane, per-cryostat deposition information.
float visE
Sum of energy deposited on plane [GeV].