8 #include "fhiclcpp/ParameterSet.h"
10 #include <TParameter.h>
14 #include "gallery/ValidHandle.h"
15 #include "canvas/Utilities/InputTag.h"
16 #include "canvas/Persistency/Common/FindMany.h"
18 #include "nusimdata/SimulationBase/MCTruth.h"
19 #include "nusimdata/SimulationBase/MCNeutrino.h"
20 #include "nusimdata/SimulationBase/MCNeutrino.h"
40 #include "../SBNOsc/Utilities.h"
41 #include "../RecoUtils/RecoUtils.h"
42 #include "../RecoUtils/GeoUtil.h"
43 #include "../NumuReco/PrimaryTrack.h"
44 #include "../NumuReco/TruthMatch.h"
47 #include "ubcore/LLBasicTool/GeoAlgo/GeoAABox.h"
48 #include "canvas/Persistency/Provenance/ProductID.h"
69 const std::vector<simb::MCParticle> &mcparticle_list = *ev.getValidHandle<std::vector<simb::MCParticle>>(
"largeant");
71 for (
const simb::MCParticle &part: mcparticle_list) {
72 if (mcparticle_id == part.TrackId()) {
73 std::cout <<
" start T: " << part.Position().T() <<
" to: " << part.EndPosition().T() << std::endl;
80 TVector3 direction = (p1 - p0) * ( 1. / (p1 - p0).Mag());
81 std::vector<TVector3> intersections = volume.
GetIntersections(p0, direction);
90 assert(intersections.size() == 2);
93 int intersection_i = ((intersections[0] - p0).Mag() < (intersections[1] - p0).Mag()) ? 0 : 1;
97 if (
abs(intersections[intersection_i].
X() - volume.
MinX()) < eps) {
101 else if (
abs(intersections[intersection_i].
X() - volume.
MaxX()) < eps) {
105 else if (
abs(intersections[intersection_i].Y() - volume.
MinY()) < eps) {
109 else if (
abs(intersections[intersection_i].Y() - volume.
MaxY()) < eps) {
113 else if (
abs(intersections[intersection_i].Z() - volume.
MinZ()) < eps) {
117 else if (
abs(intersections[intersection_i].Z() - volume.
MaxZ()) < eps) {
131 return (
int) truth_index +1;
134 return mcparticle_id;
144 unsigned n_strip = 2;
168 _selected(new
std::
vector<numu::RecoInteraction>) {}
172 fhicl::ParameterSet pconfig = config->get<fhicl::ParameterSet>(
"NumuReco");
231 _config.
CaloTag = config->get<std::string>(
"CaloTag",
"pandoraCalo");
232 _config.
PIDTag = config->get<std::string>(
"PIDTag",
"pandoraPid");
241 fhicl::ParameterSet dCV = \
242 pconfig.get<fhicl::ParameterSet>(
"containment_volume_inset");
243 double dx = dCV.get<
double>(
"x");
244 double dy = dCV.get<
double>(
"y");
245 double zfront = dCV.get<
double>(
"zfront");
246 double zback = dCV.get<
double>(
"zback");
253 double min_track_length = pconfig.get<
double>(
"MinTrackLength", 10.);
264 sbnd::CRTGeoAlg crt_geo(fProviderManager->GetGeometryProvider(), fProviderManager->GetAuxDetGeometryProvider());
265 std::vector<double> tagger_volumes = crt_geo.
CRTLimits();
268 _crt_histograms.Initialize(
"crt_all", tagger_volumes);
271 fTree->Branch(
"reco_event", &_recoEvent);
272 fTree->Branch(
"reco_vertices", &_selected);
278 void NumuReco::Finalize() {
280 if (_crt_track_matchalg != NULL)
delete _crt_track_matchalg;
281 if (_crt_hit_matchalg != NULL)
delete _crt_hit_matchalg;
282 if (_op_hit_maker != NULL)
delete _op_hit_maker;
283 if (_track_momentum_calculator != NULL)
delete _track_momentum_calculator;
284 if (_mcs_fitter != NULL)
delete _mcs_fitter;
287 _crt_histograms.Write();
300 bool NumuReco::ProcessEvent(
const gallery::Event& ev,
const std::vector<event::Interaction> &core_truth, std::vector<event::RecoInteraction>&
reco) {
301 if (_event_counter % 10 == 0) {
302 std::cout <<
"NumuReco: Processing event " << _event_counter <<
" "
303 <<
"(" << _nu_count <<
" neutrinos selected)"
307 if (_event_counter == 0) {
309 gallery::Handle<std::vector<simb::MCTruth>> mctruth_handle;
310 bool has_mctruth = ev.getByLabel(fTruthTag, mctruth_handle);
313 gallery::Handle<std::vector<simb::MCTruth>> cosmics;
314 bool has_cosmics = ev.getByLabel(_config.CorsikaTag, cosmics);
317 if (has_mctruth && has_cosmics) {
320 else if (has_cosmics) {
332 std::cout <<
"New Event! " << _event_counter << std::endl;
333 std::cout <<
"ART Event no: " << ev.eventAuxiliary().event() << std::endl;
337 bool selected =
false;
340 CollectTruthInformation(ev);
342 std::map<size_t, numu::TrueParticle> particles = MCParticleInfos();
345 _recoEvent = Reconstruct(ev, core_truth);
348 _recoEvent.particles = std::move(particles);
351 _recoEvent.type = fType;
354 for (
unsigned i = 0; i < _recoEvent.reco.size(); i++) {
358 weight *= _config.constantWeight;
366 weight *= _config.cosmicWeight;
370 _selected->push_back(vertex);
372 reco.push_back(CoreRecoInteraction(core_truth, vertex, weight));
397 ret.
is_contained = particle.NumberTrajectoryPoints() > 0;
400 int entry_point = -1;
402 int cryostat_index = -1;
405 for (
unsigned j = 0; j < particle.NumberTrajectoryPoints(); j++) {
406 for (
unsigned i = 0; i < _config.active_volumes.size(); i++) {
407 if (_config.active_volumes[i].ContainsPosition(particle.Position(j).Vect())) {
413 if (entry_point != -1)
break;
417 if (entry_point > 0) {
418 ret.
wall_enter =
GetWallCross(_config.active_volumes[cryostat_index], particle.Position(entry_point).Vect(), particle.Position(entry_point-1).Vect());
421 std::vector<geo::BoxBoundedGeo> volumes;
422 if (entry_point >= 0) {
423 volumes = _config.tpc_volumes[cryostat_index];
425 for (
int i = 0; i < volumes.size(); i++) {
426 if (volumes[i].ContainsPosition(particle.Position(entry_point).Vect())) {
445 std::vector<geoalgo::AABox> aa_volumes;
446 for (
auto const &v: volumes) {
447 aa_volumes.emplace_back(v.MinX(), v.MinY(), v.MinZ(), v.MaxX(), v.MaxY(), v.MaxZ());
455 if (entry_point >= 0) {
457 const simb::MCTrajectory &trajectory = particle.Trajectory();
458 TVector3 pos = trajectory.Position(entry_point).Vect();
459 for (
int i = entry_point+1; i < particle.NumberTrajectoryPoints(); i++) {
460 TVector3 this_point = trajectory.Position(i).Vect();
464 ret.
contained_in_cryo = _config.active_volumes[cryostat_index].ContainsPosition(this_point);
468 for (
int j = 0; j < volumes.size(); j++) {
469 if (volumes[j].ContainsPosition(this_point) && j != tpc_index) {
481 ret.
is_contained = _config.containment_volumes[cryostat_index].ContainsPosition(this_point);
487 if (!_config.active_volumes[cryostat_index].ContainsPosition(this_point) && _config.active_volumes[cryostat_index].ContainsPosition(pos)) {
492 if (InActive(this_point) && InActive(pos)) {
493 ret.
deposited_energy += trajectory.Momentum(i-1).E() - trajectory.Momentum(i).E();
495 pos = trajectory.Position(i).Vect();
498 if (exit_point < 0 && entry_point >= 0) {
499 exit_point = particle.NumberTrajectoryPoints() - 1;
501 if (exit_point < particle.NumberTrajectoryPoints() - 1) {
502 ret.
wall_exit =
GetWallCross(_config.active_volumes[cryostat_index], particle.Position(exit_point).Vect(), particle.Position(exit_point+1).Vect());
506 ret.
is_cosmic = _true_particles_to_truth.at(particle.TrackId())->Origin() != simb::kBeamNeutrino;
512 ret.
pdgid = particle.PdgCode();
514 ret.
start = (entry_point >= 0) ? particle.Position(entry_point).Vect(): TVector3(-9999, -9999, -9999);
515 ret.
start_time = (entry_point >= 0) ? particle.Position(entry_point).T() / 1000. : -9999;
516 ret.
end = (exit_point >= 0) ? particle.Position(exit_point).Vect(): TVector3(-9999, -9999, -9999);
517 ret.
end_time = (exit_point >= 0) ? particle.Position(exit_point).T() / 1000. : -9999;
519 ret.
start_momentum = (entry_point >= 0) ? particle.Momentum(entry_point).Vect() : TVector3(-9999, -9999, -9999);
520 ret.
start_energy = (entry_point >= 0) ? particle.Momentum(entry_point).E() : -9999.;
521 ret.
end_momentum = (exit_point >= 0) ? particle.Momentum(exit_point).Vect() : TVector3(-9999, -9999, -9999);
522 ret.
end_energy = (exit_point >= 0) ? particle.Momentum(exit_point).E() : -9999.;
524 ret.
ID = particle.TrackId();
529 std::map<size_t, numu::TrueParticle> NumuReco::MCParticleInfos() {
530 std::map<size_t, numu::TrueParticle> ret;
531 for (
unsigned i = 0; i < _true_particles.size(); i++) {
532 ret[_true_particles[i]->TrackId()] = MCParticleInfo(*_true_particles[i]);
538 if (track->CountValidPoints() == 0)
return 0.;
541 for (
size_t i = 1; i < track->CountValidPoints(); i++) {
543 dist += sqrt((second - first).Mag2());
549 std::array<bool, 4> NumuReco::RecoTrackTopology(
const art::Ptr<recob::Track> &
track) {
551 bool contained_in_cryo =
true;
552 bool contained_in_tpc =
true;
553 bool crosses_tpc =
false;
560 int cryostat_index = -1;
562 int containment_index = -1;
563 for (
int i = 0; i < _config.containment_volumes.size(); i++) {
564 if (_config.containment_volumes[i].ContainsPosition(start)) {
565 containment_index = i;
569 for (
int i = 0; i < _config.active_volumes.size(); i++) {
570 if (_config.active_volumes[i].ContainsPosition(start)) {
575 if (containment_index < 0) {
576 is_contained =
false;
578 std::vector<geo::BoxBoundedGeo> volumes;
579 if (cryostat_index >= 0) {
580 volumes = _config.tpc_volumes[cryostat_index];
581 for (
int i = 0; i < volumes.size(); i++) {
582 if (volumes[i].ContainsPosition(start)) {
589 contained_in_cryo =
false;
592 contained_in_tpc =
false;
596 for (
int i = 1; i < track->CountValidPoints(); i++) {
599 is_contained = _config.containment_volumes[containment_index].ContainsPosition(this_point);
601 if (contained_in_cryo) {
602 contained_in_cryo = _config.active_volumes[cryostat_index].ContainsPosition(this_point);
604 if (contained_in_cryo && !crosses_tpc) {
605 for (
int j = 0; j < volumes.size(); j++) {
606 if (volumes[j].ContainsPosition(this_point) && j != tpc_index) {
612 if (contained_in_tpc) {
613 contained_in_tpc = volumes[tpc_index].ContainsPosition(this_point);
617 return {contained_in_cryo, contained_in_tpc, crosses_tpc, is_contained};
621 std::map<size_t, numu::RecoTrack> NumuReco::RecoTrackInfo() {
622 std::map<size_t, numu::RecoTrack> ret;
623 for (
unsigned pfp_track_index = 0; pfp_track_index < _tpc_tracks.size(); pfp_track_index++) {
624 const art::Ptr<recob::Track> &
track = _tpc_tracks[pfp_track_index];
630 this_track.
ID = _tpc_tracks_to_particle_index.at(pfp_track_index);
633 this_track.
length = track->Length();
636 assert(_tpc_tracks_to_pid.at(pfp_track_index).size() == 3);
639 double chi2_proton = 0.;
640 double chi2_kaon = 0.;
641 double chi2_muon = 0.;
642 double chi2_pion = 0.;
644 int particle_pdg = 0;
645 double min_chi2 = 0.;
646 for (
int i =0; i < 3; i++) {
648 if (!_tpc_tracks_to_pid.at(pfp_track_index).at(i)->PlaneID())
continue;
649 const art::Ptr<anab::ParticleID> &particle_id = _tpc_tracks_to_pid.at(pfp_track_index).at(i);
651 if (fProviderManager->GetGeometryProvider()->SignalType(particle_id->PlaneID()) ==
geo::kCollection) {
652 n_dof += particle_id->Ndf();
653 chi2_proton += particle_id->Chi2Proton() * particle_id->Ndf();
654 chi2_kaon += particle_id->Chi2Kaon() * particle_id->Ndf();
655 chi2_pion += particle_id->Chi2Pion() * particle_id->Ndf();
656 chi2_muon += particle_id->Chi2Muon() * particle_id->Ndf();
666 std::vector<double> chi2s {chi2_proton, chi2_muon, chi2_kaon, chi2_pion};
667 int min_ind =
std::distance(chi2s.begin(), std::min_element(chi2s.begin(), chi2s.end()));
668 min_chi2 = *std::min_element(chi2s.begin(), chi2s.end());
672 else if (min_ind == 1) {
675 else if (min_ind == 2) {
678 else if (min_ind == 3) {
693 this_track.
pdgid = particle_pdg;
702 assert(_tpc_tracks_to_calo.at(pfp_track_index).size() == 3);
732 this_track.
costh = track->StartDirection().Z() / sqrt( track->StartDirection().Mag2() );
735 std::array<bool, 4> topology = RecoTrackTopology(track);
738 this_track.
start = TVector3(track->Start().X(), track->Start().Y(), track->Start().Z());
739 this_track.
end = TVector3(track->End().X(), track->End().Y(), track->End().Z());
745 if (_config.CosmicIDAllTracks) {
746 ApplyCosmicID(this_track);
749 ret[this_track.
ID] = this_track;
755 unsigned track_id = _tpc_particles_to_track_index.at(track.
ID);
756 const art::Ptr<recob::Track> &pfp_track = _tpc_tracks[track_id];
759 track.
crt_match = CRTMatching(track, *pfp_track, _tpc_tracks_to_hits.at(track_id));
764 track.
stopping_chisq_start = _stopping_cosmic_alg.StoppingChiSq(pfp_track->Vertex(), _tpc_tracks_to_calo.at(track_id));
765 track.
stopping_chisq_finish = _stopping_cosmic_alg.StoppingChiSq(pfp_track->End(), _tpc_tracks_to_calo.at(track_id));
769 std::vector<size_t> NumuReco::RecoSliceTracks(
770 const std::map<size_t, numu::RecoTrack> &
tracks,
771 const std::map<size_t, numu::RecoParticle> &particles) {
773 std::vector<size_t> ret;
775 for (
const auto &particle_pair: particles) {
776 if (tracks.count(particle_pair.first)) {
777 ret.push_back(particle_pair.first);
784 std::vector<numu::RecoParticle> NumuReco::RecoParticleInfo() {
786 std::vector<numu::RecoParticle> ret;
789 for (
size_t i = 0; i < _tpc_particles.size(); i++) {
792 this_particle.
ID = i;
801 this_particle.
daughters.assign(_tpc_particles_to_daughters[i].
begin(), _tpc_particles_to_daughters[i].
end());
807 for (
const art::Ptr<recob::Vertex> vert: _tpc_particles_to_vertex.at(i)) {
808 TVector3 vect(vert->position().X(), vert->position().Y(), vert->position().Z());
809 this_particle.
vertices.push_back(vect);
813 if (properties.count(
"IsClearCosmic")) {
819 if (properties.count(
"NuScore")) {
820 this_particle.
p_nu_score = properties.at(
"NuScore");
825 if (properties.count(
"IsNeutrino")) {
832 ret.push_back(std::move(this_particle));
843 for (
const auto &part_pair: slice.
particles) {
844 std::cout <<
"ID: " << part_pair.first <<
"\n";
847 for (
size_t pfp_index: neutrino.
daughters) {
848 std::cout <<
"Neutrino daughter ID: " << pfp_index << std::endl;
850 if (tracks.count(daughter.
ID)) {
851 if (tracks.at(daughter.
ID).length > 1
e-4) {
871 std::vector<art::Ptr<recob::Hit>> hits = _tpc_tracks_to_hits.at(pfp_track_id);
878 int mcparticle_index = -1;
879 for (
int i = 0; i < _true_particles.size(); i++) {
880 if (_true_particles[i]->TrackId() == mcp_track_id) {
881 mcparticle_index = i;
910 ret.
match_pdg = _true_particles[mcparticle_index]->PdgCode();
911 ret.
is_primary = _true_particles[mcparticle_index]->Process() ==
"primary";
915 std::vector<numu::RecoSlice> NumuReco::RecoSliceInfo(
916 std::map<size_t, numu::RecoTrack> &reco_tracks,
917 const std::vector<numu::RecoParticle> &particles) {
919 std::vector<numu::RecoSlice> ret;
921 for (
size_t i = 0; i < _tpc_slices.size(); i++) {
925 bool primary_particle_set =
false;
927 const std::vector<art::Ptr<recob::PFParticle>> &pfp_particles = _tpc_slices_to_particles.at(i);
930 for (
unsigned j = 0; j < pfp_particles.size(); j++) {
931 const art::Ptr<recob::PFParticle> pfp_part = pfp_particles[j];
932 if (pfp_part->IsPrimary()) {
933 assert(!primary_particle_set);
934 primary_particle_set =
true;
935 slice_ret.
primary_index = _tpc_slices_to_particle_index[i][j];
940 if (std::find(_tpc_slices_to_particle_index[i].
begin(), _tpc_slices_to_particle_index[i].
end(), (
unsigned)part.ID) != _tpc_slices_to_particle_index[i].end()) {
952 if (_tpc_particles_to_flashT0.size() && _tpc_particles_to_flashT0.at(slice_ret.
primary_index).size()) {
968 if (!HasPrimaryTrack(reco_tracks, slice_ret))
continue;
975 if (!_config.CosmicIDAllTracks) {
979 if (reco_tracks.count(daughter.
ID)) {
980 ApplyCosmicID(reco_tracks.at(daughter.
ID));
985 ret.push_back(std::move(slice_ret));
991 void NumuReco::CollectTruthInformation(
const gallery::Event &ev) {
992 _true_particles.clear();
993 _true_particles_to_truth.clear();
994 _true_particles_to_generator_info.clear();
997 auto const &mcparticles = ev.getValidHandle<std::vector<simb::MCParticle>>(fMCParticleTag);
998 art::fill_ptr_vector(_true_particles, mcparticles);
1001 art::FindManyP<simb::MCTruth, sim::GeneratedParticleInfo> particles_to_truth(mcparticles, ev,
"largeant");
1002 for (
unsigned i = 0; i < mcparticles->size(); i++) {
1003 _true_particles_to_truth[mcparticles->at(i).TrackId()] = particles_to_truth.at(i).at(0);
1004 _true_particles_to_generator_info[mcparticles->at(i).TrackId()] = particles_to_truth.data(i).at(0);
1008 void NumuReco::CollectTPCInformation(
const gallery::Event &ev) {
1010 _tpc_slices.clear();
1011 _tpc_tracks.clear();
1012 _tpc_particles.clear();
1013 _tpc_slices_to_particles.clear();
1014 _tpc_slices_to_particle_index.clear();
1015 _tpc_tracks_to_particles.clear();
1016 _tpc_tracks_to_particle_index.clear();
1017 _tpc_particles_to_track_index.clear();
1018 _tpc_tracks_to_calo.clear();
1019 _tpc_tracks_to_pid.clear();
1020 _tpc_tracks_to_hits.clear();
1021 _tpc_particles_to_T0.clear();
1022 _tpc_particles_to_vertex.clear();
1023 _tpc_particles_to_daughters.clear();
1024 _tpc_particles_to_metadata.clear();
1025 _tpc_particles_to_flashT0.clear();
1027 for (
const std::string &suffix: _config.TPCRecoTagSuffixes) {
1032 unsigned particle_id_offset = _tpc_particles.size();
1035 const auto &slice_handle = ev.getValidHandle<std::vector<recob::Slice>>(_config.RecoSliceTag + suffix);
1036 art::fill_ptr_vector(_tpc_slices, slice_handle);
1039 const auto &particle_handle = ev.getValidHandle<std::vector<recob::PFParticle>>(_config.PFParticleTag + suffix);
1040 art::fill_ptr_vector(_tpc_particles, particle_handle);
1043 const auto &track_handle = ev.getValidHandle<std::vector<recob::Track>>(_config.RecoTrackTag + suffix);
1044 art::fill_ptr_vector(_tpc_tracks, track_handle);
1047 art::FindManyP<recob::PFParticle> slice_to_particle(slice_handle, ev, _config.PFParticleTag + suffix);
1048 unsigned i0 = _tpc_slices_to_particle_index.size();
1049 for (
unsigned i = 0; i < slice_handle->size(); i++) {
1050 unsigned iset = i + i0;
1051 _tpc_slices_to_particles.push_back(slice_to_particle.at(i));
1052 _tpc_slices_to_particle_index.emplace_back();
1053 for (
unsigned j = 0; j < slice_to_particle.at(i).size(); j++) {
1054 _tpc_slices_to_particle_index[iset].push_back(slice_to_particle.at(i)[j]->Self() + particle_id_offset);
1055 assert(_tpc_particles[_tpc_slices_to_particle_index[iset][j]] == _tpc_slices_to_particles[iset][j]);
1060 art::FindManyP<recob::PFParticle> track_to_particle(track_handle, ev, _config.RecoTrackTag + suffix);
1061 i0 = _tpc_tracks_to_particles.size();
1062 for (
unsigned i = 0; i < track_handle->size(); i++) {
1063 unsigned iset = i + i0;
1064 _tpc_tracks_to_particles.push_back(track_to_particle.at(i).at(0));
1065 _tpc_tracks_to_particle_index.push_back(particle_id_offset + _tpc_tracks_to_particles[iset]->Self());
1066 _tpc_particles_to_track_index[particle_id_offset + _tpc_tracks_to_particles[iset]->Self()] = iset;
1068 assert(_tpc_particles[_tpc_tracks_to_particle_index[iset]] == _tpc_tracks_to_particles[iset]);
1072 art::FindManyP<anab::Calorimetry> track_to_calo(track_handle, ev, _config.CaloTag + suffix);
1073 for (
unsigned i = 0; i < track_handle->size(); i++) {
1074 _tpc_tracks_to_calo.push_back(track_to_calo.at(i));
1078 art::FindManyP<anab::ParticleID> track_to_pid(track_handle, ev, _config.PIDTag + suffix);
1079 for (
unsigned i = 0; i < track_handle->size(); i++) {
1080 _tpc_tracks_to_pid.push_back(track_to_pid.at(i));
1084 art::FindManyP<recob::Hit> track_to_hits(track_handle, ev, _config.RecoTrackTag + suffix);
1085 for (
unsigned i = 0; i < track_handle->size(); i++) {
1086 _tpc_tracks_to_hits.push_back(track_to_hits.at(i));
1090 art::FindManyP<anab::T0> particle_to_T0(particle_handle, ev, _config.PFParticleTag + suffix);
1091 for (
unsigned i = 0; i < particle_handle->size(); i++) {
1092 _tpc_particles_to_T0.push_back(particle_to_T0.at(i));
1095 gallery::Handle<art::Assns<recob::PFParticle,anab::T0,void>> assns_check;
1096 ev.getByLabel(_config.FlashMatchTag + suffix, assns_check);
1097 if (assns_check.isValid()) {
1099 art::FindManyP<anab::T0> particle_to_flash(particle_handle, ev, _config.FlashMatchTag + suffix);
1100 for (
unsigned i = 0; i < particle_handle->size(); i++) {
1101 assert(particle_to_flash.at(i).size() == 0 || particle_to_flash.at(i).size() == 1);
1102 _tpc_particles_to_flashT0.push_back(particle_to_flash.at(i));
1107 art::FindManyP<recob::Vertex> particle_to_vertex(particle_handle, ev, _config.PFParticleTag + suffix);
1108 for (
unsigned i = 0; i < particle_handle->size(); i++) {
1109 assert(particle_to_vertex.at(i).size() == 0 || particle_to_vertex.at(i).size() == 1);
1110 _tpc_particles_to_vertex.push_back(particle_to_vertex.at(i));
1114 for (
unsigned i = 0; i < particle_handle->size(); i++) {
1115 std::vector<unsigned> daughters;
1116 for (
unsigned d: _tpc_particles[i+particle_id_offset]->Daughters()) {
1117 daughters.push_back(particle_id_offset + d);
1119 _tpc_particles_to_daughters.push_back(std::move(daughters));
1123 art::FindManyP<larpandoraobj::PFParticleMetadata> pfp_metadatas(particle_handle, ev, _config.PFParticleTag + suffix);
1124 for (
unsigned i = 0; i < particle_handle->size(); i++) {
1125 _tpc_particles_to_metadata.push_back(pfp_metadatas.at(i).at(0));
1131 void NumuReco::CollectCRTInformation(
const gallery::Event &ev) {
1132 _crt_tracks_local.clear();
1133 _crt_hits_local.clear();
1136 gallery::Handle<std::vector<sbn::crt::CRTTrack>> crt_tracks_sbnd;
1137 bool has_crt_tracks_sbnd = ev.getByLabel(_config.CRTTrackTag, crt_tracks_sbnd);
1138 gallery::Handle<std::vector<sbn::crt::CRTTrack>> crt_tracks_icarus;
1140 bool has_crt_tracks_icarus =
false;
1141 _has_crt_tracks = has_crt_tracks_sbnd || has_crt_tracks_icarus;
1143 if (has_crt_tracks_icarus) {
1144 for (
unsigned i = 0; i < crt_tracks_icarus->size(); i++) {
1145 _crt_tracks_local.emplace_back();
1146 memcpy(&_crt_tracks_local[i], &crt_tracks_icarus->at(i),
sizeof(
sbn::crt::CRTTrack));
1149 _crt_tracks = (_has_crt_tracks) ?
1150 ( (has_crt_tracks_sbnd) ? crt_tracks_sbnd.product() : &_crt_tracks_local) :
1154 gallery::Handle<std::vector<sbn::crt::CRTHit>> crt_hits_sbnd;
1155 bool has_crt_hits_sbnd = ev.getByLabel(_config.CRTHitTag, crt_hits_sbnd);
1156 gallery::Handle<std::vector<sbn::crt::CRTHit>> crt_hits_icarus;
1157 bool has_crt_hits_icarus = ev.getByLabel(_config.CRTHitTag, crt_hits_icarus);
1158 _has_crt_hits = has_crt_hits_sbnd || has_crt_hits_icarus;
1161 if (has_crt_hits_icarus) {
1162 for (
unsigned i = 0; i < crt_hits_icarus->size(); i++) {
1167 _crt_hits = (_has_crt_hits) ?
1168 ( (has_crt_hits_sbnd) ? crt_hits_sbnd.product() : &_crt_hits_local) :
1179 std::pair<sbn::crt::CRTTrack, double> closest_crt_track = { {}, -99999 };
1181 if (_has_crt_tracks) {
1182 closest_crt_track = _crt_track_matchalg->ClosestCRTTrackByAngle(pandora_track, hits, *_crt_tracks);
1186 if (closest_crt_track.second > -10000 ) {
1188 if (_config.TSMode == 0) match.
track.
time = closest_crt_track.first.ts0_ns / 1000. ;
1189 else match.
track.
time = closest_crt_track.first.ts1_ns / 1000. ;
1190 match.
track.
angle = closest_crt_track.second;
1199 std::pair<sbn::crt::CRTHit, double> hit_pair = std::pair<sbn::crt::CRTHit, double>({
sbn::crt::CRTHit(), -1});
1200 if (_has_crt_hits) {
1202 if (_config.CRTHitinOpHitRange && flash_match.
present) {
1204 double time_width = (_config.CRT2OPTimeWidth) / 2;
1205 std::pair<double, double> time_range;
1206 time_range.first = match.
time - time_width;
1207 time_range.second = match.
time + time_width;
1209 hit_pair = _crt_hit_matchalg->ClosestCRTHit(pandora_track, time_range, *_crt_hits, drift_dir);
1213 hit_pair = _crt_hit_matchalg->ClosestCRTHit(pandora_track, hits, *_crt_hits);
1218 if (distance >= 0 ) {
1221 match.
hit = SBND2numuCRTHit(hit_pair.first);
1233 void NumuReco::CollectPMTInformation(
const gallery::Event &ev) {
1237 _op_hit_ptrs.clear();
1238 _op_hits_local.clear();
1243 art::ProductID local_opdets(
"local_opdets");
1244 if (_config.MakeOpHits) {
1245 const std::vector<raw::OpDetWaveform> &op_waveforms = *ev.getValidHandle<std::vector<raw::OpDetWaveform>>(
"opdaq");
1246 _op_hits_local = _op_hit_maker->MakeHits(op_waveforms);
1247 for (
unsigned i = 0; i < _op_hits_local.size(); i++) {
1248 _op_hit_ptrs.emplace_back(local_opdets, &_op_hits_local[i], i);
1252 gallery::Handle<std::vector<recob::OpHit>> op_hits;
1253 ev.getByLabel(_config.OpFlashTag, op_hits);
1254 art::fill_ptr_vector(_op_hit_ptrs, op_hits);
1268 if (fProviderManager->GetPhotonBackTrackerProvider() == NULL) {
1277 const std::vector<art::Ptr<recob::OpHit>> hit_matches = fProviderManager->GetPhotonBackTrackerProvider()->TrackIdToOpHits_Ps(photon_mother_id, _op_hit_ptrs);
1278 if (hit_matches.size() > 0) {
1280 double average = 0.;
1281 double match_pe = 0.;
1282 double min_time = 99999999.;
1283 for (
const art::Ptr<recob::OpHit> op_hit: hit_matches) {
1284 average += op_hit->PE() * op_hit->PeakTime();
1285 match_pe += op_hit->PE();
1286 if (op_hit->PeakTime() < min_time) {
1287 min_time = op_hit->PeakTime();
1291 double match_time = average / match_pe;
1293 match.
time = min_time;
1301 bool NumuReco::InBeamSpill(
float time) {
1302 return time > _config.BeamSpillWindow[0] && time < _config.BeamSpillWindow[1];
1307 if (_config.TSMode == 0) ret.
time = (int)hit.
ts0_ns / 1000. ;
1309 ret.
time += _config.CRTHitTimeCorrection;
1316 void NumuReco::FillCRTHits() {
1318 _crt_histograms.Fill(
hit);
1322 std::vector<numu::CRTHit> NumuReco::InTimeCRTHits() {
1323 std::vector<numu::CRTHit> ret;
1327 if (InBeamSpill(this_hit.
time)) {
1328 ret.push_back(this_hit);
1332 return std::move(ret);
1335 numu::RecoEvent NumuReco::Reconstruct(
const gallery::Event &ev,
const std::vector<event::Interaction> &truth) {
1337 CollectCRTInformation(ev);
1338 CollectPMTInformation(ev);
1339 CollectTPCInformation(ev);
1342 std::vector<numu::RecoParticle> reco_particles = RecoParticleInfo();
1345 std::map<size_t, numu::RecoTrack> reco_tracks = RecoTrackInfo();
1348 std::vector<numu::RecoSlice> reco_slices = RecoSliceInfo(reco_tracks, reco_particles);
1350 std::vector<numu::RecoInteraction>
reco;
1351 for (
unsigned reco_i = 0; reco_i < reco_slices.size(); reco_i++) {
1352 const numu::RecoParticle &neutrino = reco_slices[reco_i].particles.at(reco_slices[reco_i].primary_index);
1356 this_interaction.
slice = reco_slices[reco_i];
1369 reco.push_back(std::move(this_interaction));
1373 event.
reco = std::move(reco);
1374 event.tracks = std::move(reco_tracks);
1377 event.in_time_crt_hits = InTimeCRTHits();
1378 gallery::Handle<std::vector<raw::OpDetWaveform>> waveforms;
1379 if (ev.getByLabel(
"opdaq", waveforms)) {
1380 double tick_period = fProviderManager->GetDetectorClocksProvider()->OpticalClock().TickPeriod();
1381 int threshold = _config.PMTTriggerThreshold;
1382 bool is_sbnd = fExperimentID ==
kExpSBND;
1383 std::pair<double, double> window;
1384 if (is_sbnd) window = {0., 2.};
1385 else window = {1500., 1502.};
1386 event.flash_trigger_primitives =
numu::TriggerPrimitives(*waveforms, tick_period, window, threshold, is_sbnd);
1393 return std::move(event);
1396 bool NumuReco::InActive(
const TVector3 &v)
const {
1397 for (
auto const& active: _config.active_volumes) {
1398 if (active.ContainsPosition(v))
return true;
std::map< int, art::Ptr< simb::MCTruth > > _true_particles_to_truth
bool verbose
Whether to print out info associated w/ selection.
float time
Time of flash [us].
InteractionMode mode
Mode of the interaction.
float z_err
position uncertainty in z-direction (cm).
bool mctruth_has_neutrino
Whether the MCTruth object this track matches to is a neutrino interaction.
Track track
CRT Track match.
int pdgid
Particle ID that minimizes chi2.
TVector3 start_momentum
Particle directional momentum for first trajectory point inside TPC AV [GeV].
float x_err
position uncertainty in x-direction (cm).
std::map< uint8_t, std::vector< std::pair< int, float > > > pesmap
Saves signal hit information (FEB, local-channel and PE) .
bool requireTrack
Apply cut that requires each reconstructed vertex to have an associated primary track.
void Initialize(fhicl::ParameterSet *config=NULL)
double std(const std::vector< short > &wf, const double ped_mean, size_t start, size_t nsample)
std::vector< geo::BoxBoundedGeo > ActiveVolumes(const geo::GeometryCore *geometry)
std::array< float, 2 > BeamSpillWindow
float chi2_muon
Chi2 of dE/dx to muon hypotheis. Combined agaisnt all planes.
float chi2_kaon
Chi2 of dE/dx to kaon hypotheis. Combined against all planes.
int ID
ID/index of this particle (taken from MCParticle ID)
int mctruth_ccnc
CC (1) / NC (0) value of the MCTruth this object matches to.
void reconfigure(const core::ProviderManager &manager, const Config &config)
int pandora_pid
Particle ID from pandora.
float bwd_mcs_momentum_err
MCS momentum calculation fit error under hypothesis track is backward.
MCSFitResult mcs_proton
MCS calculation result for Proton PID hypothesis.
MCSFitResult mcs_pion
MCS calculation result for Pion PID hypothesis.
std::vector< uint8_t > feb_id
FEB address.
ClusterModuleLabel join with tracks
double ts1_ns
Timestamp T1 ([signal time w.r.t. Trigger time]), in UTC absolute time scale in nanoseconds from the ...
Encapsulate the construction of a single cyostat.
float distance
//!< Distance from projected track to CRT Hit. Nonsense if present is false.
const unsigned int & TriggerType() const
int mctruth_origin
Value of Origin_t enum of the MCTruth object this track matches to.
int GetPhotonMotherID(int mcparticle_id)
bool is_cosmic
Whether this particle is of cosmic origin.
CRTMatch crt_match
CRTMatch.
int plane
Name of the CRT wall (in the form of numbers).
bool present
Whether this CRTMatch has a matching track.
const double & Time() const
float peshit
Total photo-electron (PE) in a crt hit.
float bwdMomentum() const
momentum value from fit assuming a backward track direction
TruthMatch match
Info for mathing to truth.
StoppingParticleCosmicIdAlg _stopping_cosmic_alg
Algorithm for doing cosmic ID using a fit to the energy deposits.
float y_err
position uncertainty in y-direction (cm).
std::vector< std::vector< geo::BoxBoundedGeo > > tpc_volumes
List of active tpc volumes – retreived from Geoemtry service.
Declaration of signal hit object.
int mcparticle_id
MCParticle ID of the particle this track matches to (same as the ID of the RecoTrack of that particle...
std::string CRTTrackTag
art tag for CRT tracks
float min_chi2
Minimum chi2 value across all hypotheses.
int primary_track_index
Index of the primary track.
float fwdMomUncertainty() const
momentum uncertainty from fit assuming a forward track direction
double MinX() const
Returns the world x coordinate of the start of the box.
const detinfo::DetectorPropertiesStandard * GetDetectorPropertiesProvider() const
std::vector< FlashTriggerPrimitive > TriggerPrimitives(const std::vector< raw::OpDetWaveform > &waveforms, double tick_period, std::pair< double, double > &window, int thresh, bool is_sbnd)
unsigned pe
number of photo electons in flash
return track match has_match and!particle is_contained
TVector3 end_momentum
Particle directional momentum for last trajectory point inside TPC AV [GeV].
int PdgCode() const
Return the type of particle as a PDG ID.
double MaxX() const
Returns the world x coordinate of the end of the box.
void reconfigure(const core::ProviderManager &manager, const Config &config)
process_name use argoneut_mc_hitfinder track
sbn::crt::CRTHit ICARUS2SBNDCrtHit(const sbn::crt::CRTHit &inp)
process_name opflashCryoW ana
bool is_contained
is it contained in a single cryostat active volume
then echo echo For and will not be changed by echo further linking echo echo B echo The symbol is in the uninitialized data multiple common symbols may appear with the echo same name If the symbol is defined the common echo symbols are treated as undefined references For more echo details on common see the discussion of warn common echo in *Note Linker see the discussion of warn common echo in *Note Linker such as a global int variable echo as opposed to a large global array echo echo I echo The symbol is an indirect reference to another symbol This echo is a GNU extension to the a out object file format which is echo rarely used echo echo N echo The symbol is a debugging symbol echo echo R echo The symbol is in a read only data section echo echo S echo The symbol is in an uninitialized data section for small echo objects echo echo T echo The symbol is in the the normal defined echo symbol is used with no error When a weak undefined symbol echo is linked and the symbol is not the value of the echo weak symbol becomes zero with no error echo echo W echo The symbol is a weak symbol that has not been specifically echo tagged as a weak object symbol When a weak defined symbol echo is linked with a normal defined the normal defined echo symbol is used with no error When a weak undefined symbol echo is linked and the symbol is not the value of the echo weak symbol becomes zero with no error echo echo echo The symbol is a stabs symbol in an a out object file In echo this the next values printed are the stabs other echo the stabs desc and the stab type Stabs symbols are echo used to hold debugging information For more echo see *Note or object file format specific echo echo For Mac OS X
std::vector< size_t > daughters
Daughters of the particle in the "particle flow". Value represents index into pandora information...
float length
Length of track contained in any TPC active volume [cm].
double ts0_ns_corr
[Honestly, not sure at this point, it was there since long time (BB)]
TVector3 start
start position of track
std::vector< std::string > TPCRecoTagSuffixes
float stopping_chisq_finish
Chi2 fraction of stopping vs. not-stopping hypotheis to track end point.
ApaCrossCosmicIdAlg _apa_cross_cosmic_alg
Algorithm for doing cosmic ID by looking for tracks crossing APA.
const geo::GeometryCore * GetGeometryProvider() const
double ts0_s_corr
[Honestly, not sure at this point, it was there since long time (BB)]
TVector3 uncertainty
Uncertainty on the location of the hit.
uint64_t ts0_s
Second-only part of timestamp T0.
trkf::TrackMomentumCalculator * _track_momentum_calculator
Calculator for range-based track momentum.
double trackMatchContainmentCut
TVector3 location
Location of the hit.
float p_nu_score
Take from Pandora metadata "nu_score".
bool SelectSlice(const caf::SRSlice &slice, bool cut_clear_cosmic)
std::vector< RecoInteraction > reco
List of reconstructed vertices.
float bwd_mcs_momentum
MCS momentum calculation under hypothesis track is backward.
float z_pos
position in z-direction (cm).
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
double ts0_ns
Timestamp T0 (from White Rabbit), in UTC absolute time scale in nanoseconds from the Epoch...
Access the description of detector geometry.
bool crosses_tpc
does it cross a tpc?
float end_energy
Particle energy for last point inside TPC AV [GeV].
TVector3 position
location of the vertex
Contains truth level information and additional fields for selection-defined reconstruction informati...
float reco_energy
Reconstructed neutrino energy [GeV].
std::vector< std::string > uniformWeights
Weights taken from "EventWeight" that should be applied to the weight of each event.
MCSFitResult mcs_kaon
MCS calculation result for Kaon PID hypothesis.
process_name standard_reco_uboone reco
double distance(geo::Point_t const &point, CathodeDesc_t const &cathode)
Returns the distance of a point from the cathode.
Metadata associated to PFParticles.
double TrackCompletion(const core::ProviderManager &manager, int mcparticle_id, const std::vector< art::Ptr< recob::Hit >> &reco_track_hits)
bool requireContained
Apply cut that requires each primary track to be contained inside the containment volume...
bool contained_in_cryo
is it contained a single cryostat?
sbnd::CRTTrackMatchAlg * _crt_track_matchalg
Algorithm for matching reco Tracks -> CRT Tracks.
TVector3 start
start position of track
float range_momentum_muon
Range momentum calculation of the track using range under the assumption it is a muon [GeV]...
TVector3 mctruth_vertex
The interaction vertex of the MCTruth object this track matches to.
float start_energy
Particle energy for first point inside TPC AV [GeV].
FlashMatch flash_match
Result of flash matching algorithm on this slice.
TVector3 end
end position of track
float weight
Selection-defined event weight.
float chi2_pion
Chi2 of dE/dx to pion hypotheis. Combined against all planes.
numu::Wall GetWallCross(const geo::BoxBoundedGeo &volume, const TVector3 p0, const TVector3 p1)
double cosmicWeight
Weight applied to all events matched to a cosmic track.
bool requireMatched
Apply cut that requires each reconstructed vertex to be matched to a truth vertex.
float length
Length of track.
unsigned PMTTriggerThreshold
const PropertiesMap & GetPropertiesMap() const
std::map< int, const sim::GeneratedParticleInfo * > _true_particles_to_generator_info
sbnd::CRTT0MatchAlg * _crt_hit_matchalg
Algorithm for matching reco Tracks -> CRT hits (T0's)
auto end(FixedBins< T, C > const &) noexcept
double MinZ() const
Returns the world z coordinate of the start of the box.
bool present
Whether this CRTMatch has a matching hit.
int TrueParticleIDFromTotalTrueEnergy(const core::ProviderManager &manager, const std::vector< art::Ptr< recob::Hit > > &hits, bool rollup_unsaved_ids=1)
float completion
Fraction of energy deposits by true particle matched by this track.
opdet::opHitFinderSBND * _op_hit_maker
Optical hit maker.
#define DECLARE_SBN_PROCESSOR(classname)
Electron neutrino event selection.
back track the reconstruction to the simulation
required by fuzzyCluster table::sbnd_g4_services gaushitTruthMatch fmatch
float fwd_mcs_momentum
MCS momentum calculation under hypothesis track is forward.
TruthMatch InteractionTruthMatch(const std::vector< event::Interaction > &truth, const std::map< size_t, numu::RecoTrack > &reco_tracks, const numu::RecoInteraction &reco)
float stopping_chisq_start
Chi2 fraction of stopping vs. not-stopping hypothesis to track start points.
std::vector< TVector3 > vertices
List of vertices associated with the particle.
const detinfo::DetectorClocksStandard * GetDetectorClocksProvider() const
double flashMatchTimeDifference
std::string FlashMatchTag
bool has_match
Whether a track match exists.
bool crosses_tpc
does it cross a tpc?
Provides recob::Track data product.
std::vector< std::vector< geo::BoxBoundedGeo > > TPCVolumes(const geo::GeometryCore *geometry)
std::vector< geo::BoxBoundedGeo > containment_volumes
List of volumes for containment cuts – set by "containment_volumes".
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)
std::string CorsikaTag
art tag for corsika MCTruth
double MaxY() const
Returns the world y coordinate of the end of the box.
Class storing the result of the Maximum Likelihood fit of Multiple Coulomb Scattering angles between ...
void DumpTrueStart(const gallery::Event &ev, int mcparticle_id)
auto begin(FixedBins< T, C > const &) noexcept
static const TVector3 InvalidTVector3
bool is_primary
Whether this track was produced as the "primary" process.
double CRTHitTimeCorrection
std::vector< geo::BoxBoundedGeo > active_volumes
List of active volumes per cryostat.
float deposited_energy
Total particle energy depositive in TPC AV [GeV].
float y_pos
position in y-direction (cm).
TrackTruthMatch match
Truth matching information.
bool p_is_neutrino
Taken from Pandora metadata "is_neutrino".
int SelectLongestTrack(const std::map< size_t, RecoTrack > &tracks, const RecoSlice &slice)
float nu_energy
true/reconstructed neutrino energy
bool p_is_clear_cosmic
Taken from Pandora metadata "is_clear_cosmic".
float bwdMomUncertainty() const
momentum uncertainty from fit assuming a backward track direction
RecoSlice slice
Particle content of the interaction.
Hierarchical representation of particle flow.
const double & TriggerConfidence() const
int pid_n_dof
Number of d.o.f. in chi2 fit.
A base class aware of world box coordinatesAn object describing a simple shape can inherit from this ...
std::string PFParticleTag
art tag for PFParticles
int mctruth_vertex_id
index of the truth vertex into the list of MCThruths. -1 if no match
constexpr double dist(const TReal *x, const TReal *y, const unsigned int dimension)
int DriftDirectionFromHits(const geo::GeometryCore *GeometryService, std::vector< art::Ptr< recob::Hit >> hits)
float x_pos
position in x-direction (cm).
double containedLength(const TVector3 &v0, const TVector3 &v1, const std::vector< geoalgo::AABox > &boxes)
int pdgid
Particle ID code.
double MaxZ() const
Returns the world z coordinate of the end of the box.
float pes
Number of PE's in hit.
trkf::TrajectoryMCSFitter * _mcs_fitter
Calculator for MCS based momentum.
Config _config
The config.
bool contained_in_tpc
is it contained in a single TPC?
std::map< size_t, RecoParticle > particles
Map of particle index to particle information.
int multiplicity
Number of tracks in this interaction.
ProviderManager * fProviderManager
Interface for provider access.
double constantWeight
Constant weight to apply uniformly to each event.
std::vector< TVector3 > GetIntersections(TVector3 const &TrajectoryStart, TVector3 const &TrajectoryDirect) const
Calculates the entry and exit points of a trajectory on the box surface.
std::vector< size_t > tracks
List of track indices contained in this slice.
Class for Maximum Likelihood fit of Multiple Coulomb Scattering angles between segments within a Trac...
float angle
Angle between TPC track and CRT track.
Header for the ParticleInvenotry Service Provider.
float range_momentum_proton
Range momentum calculation of track using range using the assumption it is a proton [GeV]...
TVector3 end
end position of track
float score
score of flash matching
int primary_index
Index of the primary particle of this slice.
std::vector< double > CRTLimits() const
float fwdMomentum() const
momentum value from fit assuming a forward track direction
int match_pdg
PDG of the MCParticle this track matches to.
std::string MCParticleTag
art tag for MCParticle
MCSFitResult mcs_muon
MCS calculation result for Muon PID hypothesis.
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
int ID
ID/index of this track. Does not necessarily correspond to the Pandora index.
Wall wall_enter
the face of the TPC that the particle crosses on enter
Wall wall_exit
the face of the TPC that the particle crosses on exit
double MinY() const
Returns the world y coordinate of the start of the box.
const art::Ptr< simb::MCTruth > & TrackIdToMCTruth_P(int const &id) const
std::string tagger
Name of the CRT wall (in the form of strings).
float fwd_mcs_momentum_err
MCS momentum calculation fit error under hypothesis track is forward.
HitMatch hit_match
CRT Hit match.
physics associatedGroupsWithLeft p1
BEGIN_PROLOG could also be cout
Track from a non-cascading particle.A recob::Track consists of a recob::TrackTrajectory, plus additional members relevant for a "fitted" track:
std::string RecoTrackTag
art tag for reconstructed tracks
float costh
cosine of angle to z axis
Encapsulate the construction of a single detector plane.
double RecoTrackLength(const art::Ptr< recob::Track > &track)
Signal from collection planes.
float start_time
start time of track
std::string RecoVertexTag
art tag for reconstructed vertices
float end_time
end time of track
float time
Matching time [us] of track. T==0 is set to beam spill start time.
float chi2_proton
Chi2 of dE/dx to proton hypothesis. Combined against all planes.