10 #include "nug4/ParticleNavigation/EmEveIdCalculator.h" 14 #include "Utilities/AssociationUtil.h" 17 #include "CoreUtils/ServiceUtil.h" 30 : fClocks(nullptr), fGeo(nullptr) {
32 fClocks = gar::providerFrom<detinfo::DetectorClocksServiceGAr>();
33 fGeo = gar::providerFrom<geo::GeometryGAr>();
72 <<
"Attempting to backtrack without MC truth information";
84 <<
"can't find particle with track id " <<
id 85 <<
" in sim::ParticleList returning null pointer";
89 return part_it->second;
98 <<
"Attempting to backtrack without MC truth information";
111 <<
"Attempting to backtrack without MC truth information";
121 if (walker==
nullptr)
return nullptr;
122 while ( walker !=
nullptr &&
134 (*fECALTrackToTPCTrack)[dejaVu] = walker->
TrackId();
144 <<
"Attempting to backtrack without MC truth information";
156 while ( walker !=
nullptr &&
169 (*fECALTrackToTPCTrack)[trackID] = walker->
TrackId();
180 <<
"Attempting to backtrack without MC truth information";
183 if (forebear==
nullptr || afterbear==
nullptr)
return false;
185 int stopper = forebear->
TrackId();
186 int walker = afterbear->
TrackId();
187 while ( walker!=stopper ) {
207 <<
"Attempting to backtrack without MC truth information";
217 <<
"attempting to find MCTruth index for out-of-range value: " 228 <<
"Attempting to backtrack without MC truth or gar::rec::Hit information";
234 std::vector<HitIDE> ides;
235 ides = this->
ChannelToHitIDEs(hit->Channel(),hit->StartTime(),hit->EndTime());
244 <<
"Attempting to backtrack without MC truth or gar::rec::Hit information";
250 std::vector<HitIDE> ides;
258 std::vector<art::Ptr<rec::Hit>>
261 bool checkNeutrals)
const {
267 <<
"Attempting to backtrack without MC truth or gar::rec::Hit information";
270 std::vector<art::Ptr<rec::Hit>> hitList;
272 bool obviousNeutral = PDGpid==22 || PDGpid==2112 || PDGpid==111 ||
273 abs(PDGpid)==14 ||
abs(PDGpid)==12;
274 if (!checkNeutrals && obviousNeutral)
return hitList;
277 std::vector<HitIDE> hids;
279 for (
auto hit : allhits) {
284 for (
auto const& hid : hids) {
286 hitList.push_back(
hit);
299 double const start,
double const stop)
const {
303 if(start<0 || stop <0)
304 MF_LOG_WARNING(
"BackTrackerCore::ChannelToHitIDEs") <<
"start and/or stop times are negative!";
305 std::vector<HitIDE> hitIDEs;
309 <<
"Attempting to find energy deposits for channel " << channel
311 <<
" channels available, returning an empty vector.";
317 if(chanEDeps.size() < 1){
319 <<
"No sdp::EnergyDeposits for selected channel: " << channel
320 <<
". There is no way to backtrack the given hit, returning" 321 <<
" an empty vector.";
325 std::map<int,size_t> tidmap;
329 unsigned short tdc = 0;
330 float chanpos[3]={0.,0.,0};
336 double totalEallTracks = 0.0;
338 for (
auto const& edepfrac : chanEDeps) {
340 auto edep = edepfrac.first;
341 float weight = edepfrac.second;
342 if(weight<0 || weight>1)
343 MF_LOG_WARNING(
"BackTrackerCore::ChannelToHitIDEs") <<
"bad weight (" << weight <<
")";
348 if ( (
unsigned int)start <= tdc && tdc <= (
unsigned int)stop) {
350 MF_LOG_DEBUG(
"BackTrackerCore::ChannelToHitIDEs") <<
"edep energy: " << edep->Energy()
351 <<
", weight: " << weight <<
", contributed energy: " <<
energy;
352 totalEallTracks +=
energy;
354 TLorentzVector simpos(edep->X(),edep->Y(),edep->Z(),edep->Time());
364 int tid =
abs( edep->TrackID() );
365 auto tidmapiter = tidmap.find(tid);
366 if (tidmapiter == tidmap.end()) {
367 hitIDEs.emplace_back(tid, 0.0, energy, simpos, simmom);
368 tidmap[tid] = hitIDEs.size()-1;
370 hitIDEs.at(tidmapiter->second).energyTot +=
energy;
371 hitIDEs.at(tidmapiter->second).position += simpos;
372 hitIDEs.at(tidmapiter->second).momentum += simmom;
384 for (
size_t i = 0; i < hitIDEs.size(); ++i) {
385 hitIDEs[i].energyFrac = hitIDEs[i].energyTot / totalEallTracks;
386 hitIDEs[i].position *= 1.0/totalEallTracks;
387 hitIDEs[i].momentum *= 1.0/totalEallTracks;
391 size_t nbefore = hitIDEs.size();
392 std::sort(hitIDEs.begin(),hitIDEs.end());
393 hitIDEs.erase(std::unique(hitIDEs.begin(),hitIDEs.end()),hitIDEs.end());
394 size_t nafter = hitIDEs.size();
396 MF_LOG_WARNING(
"BackTrackerCore::ChannelToHitIDEs") <<
"found and removed " 397 << nbefore-nafter <<
" duplicate HitIDEs (not expected for single channel)";
405 std::pair<double,double>
411 <<
"Attempting to backtrack without MC truth or gar::rec::Hit information";
420 for (
auto hit : hits) {
423 weight = (weightByCharge) ?
hit->Signal() : 1.0;
426 for (
auto iHitIDE : hitIDEs) {
428 if (iHitIDE.trackID == trackIDin &&
437 double uncertainty = 0.0;
439 purity = desired/
total;
440 uncertainty = std::sqrt( desired*(total -desired)/total )/
total;
442 return std::make_pair(purity,uncertainty);
448 std::pair<double,double>
455 <<
"Attempting to backtrack without MC truth or gar::rec::Hit information";
462 for (
auto hit : hits) {
465 weight = (weightByCharge) ?
hit->Signal() : 1.0;
467 for (
auto iHitIDE : hitIDEs) {
469 if (iHitIDE.trackID == trackIDin &&
480 for (
auto hit : allhits) {
483 weight = (weightByCharge) ?
hit->Signal() : 1.0;
485 for (
auto iHitIDE : hitIDEs) {
487 if (iHitIDE.trackID == trackIDin &&
496 double efficiency = 0.0;
497 double uncertainty = 0.0;
499 efficiency = desired/
total;
500 uncertainty = std::sqrt( desired*(total -desired)/total )/
total;
502 return std::make_pair(efficiency,uncertainty);
514 <<
"Attempting to backtrack without MC truth or gar::rec::CaloHit information";
518 std::vector<CalIDE> ides;
528 <<
"Attempting to backtrack without MC truth or gar::rec::CaloHit information";
532 std::vector<CalIDE> ides;
540 std::vector<art::Ptr<rec::CaloHit>>
548 <<
"Attempting to backtrack without MC truth or gar::rec::CaloHit information";
551 std::vector<art::Ptr<rec::CaloHit>> calHitList;
553 std::vector<CalIDE> calhids;
555 for (
auto hit : allhits) {
560 for (
auto const& hid : calhids) {
562 calHitList.push_back(
hit);
574 float const time)
const {
578 std::vector<CalIDE> calIDEs;
580 std::vector<const sdp::CaloDeposit*> cellEDeps;
584 catch (std::out_of_range &) {
586 <<
"No sdp::EnergyDeposits for selected ECAL cell: " << cell
587 <<
". There is no way to backtrack the given calorimeter hit," 588 <<
" returning an empty vector.";
592 std::map<int,size_t> tidmap;
598 double totalEallTracks = 0.0;
599 for (
auto const& edep : cellEDeps) {
602 if ( start<=edep->Time() && edep->Time()<=stop) {
603 float energy = edep->Energy();
604 totalEallTracks +=
energy;
605 int tid = edep->TrackID();
611 if (TPCEve!=
nullptr) {
616 auto tidmapiter = tidmap.find(tidTPC);
617 if (tidmapiter == tidmap.end()) {
618 calIDEs.emplace_back(tidTPC, 0.0, energy);
619 tidmap[tidTPC] = calIDEs.size()-1;
621 calIDEs.at(tidmapiter->second).energyTot +=
energy;
627 for (
size_t i = 0; i < calIDEs.size(); ++i) {
628 calIDEs[i].energyFrac = calIDEs[i].energyTot / totalEallTracks;
636 std::pair<double,double>
642 <<
"Attempting to backtrack without MC truth or gar::rec::Hit information";
651 for (
auto hit : hits) {
654 weight = (weightByCharge) ?
hit->Energy() : 1.0;
657 for (
auto iCalIDE : calIDEs) {
659 if (iCalIDE.trackID == trackIDin &&
668 double uncertainty = 0.0;
670 purity = desired/
total;
671 uncertainty = std::sqrt( desired*(total -desired)/total )/
total;
673 return std::make_pair(purity,uncertainty);
679 std::pair<double,double>
686 <<
"Attempting to backtrack without MC truth or gar::rec::Hit information";
693 for (
auto hit : hits) {
696 weight = (weightByCharge) ?
hit->Energy() : 1.0;
698 for (
auto iCalIDE : calIDEs) {
700 if (iCalIDE.trackID == trackIDin &&
711 for (
auto hit : allhits) {
714 weight = (weightByCharge) ?
hit->Energy() : 1.0;
716 for (
auto iCalIDE : calIDEs) {
718 if (iCalIDE.trackID == trackIDin &&
727 double efficiency = 0.0;
728 double uncertainty = 0.0;
730 efficiency = desired/
total;
731 uncertainty = std::sqrt( desired*(total -desired)/total )/
total;
733 return std::make_pair(efficiency,uncertainty);
741 std::vector<art::Ptr<rec::Hit>>
const 747 std::vector<art::Ptr<gar::rec::Hit>> retval;
762 std::vector<art::Ptr<rec::Hit>>
const 766 std::vector<art::Ptr<gar::rec::Hit>> retval;
775 std::vector<const rec::TPCCluster*>
const 780 std::vector<const gar::rec::TPCCluster*> retval;
791 std::vector<art::Ptr<rec::Hit>>
const hits =
TrackToHits(t);
792 std::vector<HitIDE> allIdes;
795 for(
auto const&
hit : hits) {
797 allIdes.insert(allIdes.end(),ides.begin(),ides.end());
812 for(
auto const& ide : allIdes) {
813 etot += ide.energyTot;
822 std::vector<std::pair<simb::MCParticle*,float>>
826 std::vector<art::Ptr<gar::rec::Hit>>
const hitCol =
TrackToHits(t);
827 std::vector<HitIDE> hitIDECol;
828 for (
auto hit : hitCol) {
830 hitIDECol.insert(hitIDECol.end(), IDEsThisHit.begin(),IDEsThisHit.end());
834 std::map<int,float> lTrackIdToEnergy;
835 for (
auto hitIDE : hitIDECol) {
836 lTrackIdToEnergy[hitIDE.trackID] += hitIDE.energyFrac * hitIDE.energyTot;
842 for (; iTrackIdTo != lTrackIdToEnergy.end(); ++iTrackIdTo) {
845 if ( lTrackIdToEnergy.count(iPart->
Mother())==1 ) {
846 lTrackIdToEnergy[iPart->
Mother()] += iTrackIdTo->second;
847 iTrackIdTo = lTrackIdToEnergy.erase(iTrackIdTo);
848 if (iTrackIdTo != lTrackIdToEnergy.begin()) --iTrackIdTo;
858 typedef std::function<bool(std::pair<int,float>, std::pair<int,float>)> Comparator;
860 std::set<std::pair<int,float>, Comparator> setOfTracks(
861 lTrackIdToEnergy.begin(), lTrackIdToEnergy.end(),
862 [](std::pair<int,float>
a ,std::pair<int,float>
b) {
863 return a.second >
b.second;
869 auto iTrackSet = setOfTracks.begin();
870 for (; iTrackSet!=setOfTracks.end(); ++iTrackSet) {
871 Etot += iTrackSet->second;
874 std::pair<simb::MCParticle*,float> emptee(
nullptr,0.0);
875 std::vector<std::pair<simb::MCParticle*,float>> retval(setOfTracks.size(),emptee);
876 std::vector<std::pair<simb::MCParticle*,float>>
::iterator iRetval = retval.begin();
877 iTrackSet = setOfTracks.begin();
878 for (; iTrackSet != setOfTracks.end(); ++iTrackSet,++iRetval) {
880 iRetval->second = iTrackSet->second / Etot;
889 std::vector<art::Ptr<rec::Track>>
894 std::vector<art::Ptr<rec::Track>> retval;
895 std::vector<std::pair<simb::MCParticle*,float>> fromMatch;
896 int desiredTrackId = p->
TrackId();
903 for (std::pair<simb::MCParticle*,float>
matches : fromMatch) {
904 if (
matches.first->TrackId() == desiredTrackId &&
906 retval.push_back( iTrack );
918 std::vector<art::Ptr<rec::CaloHit>>
const 922 std::vector<art::Ptr<gar::rec::CaloHit>> retval;
932 std::vector<std::pair<simb::MCParticle*,float>>
937 std::vector<CalIDE> hitIDECol;
938 for (
auto hit : hitCol) {
940 hitIDECol.insert(hitIDECol.end(), IDEsThisHit.begin(),IDEsThisHit.end());
944 std::map<int,float> lClusterIdToEnergy;
945 for (
auto calIDE : hitIDECol) {
948 int iTrackID = incomingTrack->
TrackId();
949 lClusterIdToEnergy[iTrackID] += calIDE.energyFrac * calIDE.energyTot;
954 typedef std::function<bool(std::pair<int,float>, std::pair<int,float>)> Comparator;
956 std::set<std::pair<int,float>, Comparator> setOfTracks(
957 lClusterIdToEnergy.begin(), lClusterIdToEnergy.end(),
958 [](std::pair<int,float>
a ,std::pair<int,float>
b) {
959 return a.second >
b.second;
965 auto iTrackSet = setOfTracks.begin();
966 for (; iTrackSet!=setOfTracks.end(); ++iTrackSet) {
967 Etot += iTrackSet->second;
970 std::pair<simb::MCParticle*,float> emptee(
nullptr,0.0);
971 std::vector<std::pair<simb::MCParticle*,float>> retval(lClusterIdToEnergy.size(),emptee);
973 std::vector<std::pair<simb::MCParticle*,float>>
::iterator iRetval = retval.begin();
974 iTrackSet = setOfTracks.begin();
975 for (; iTrackSet != setOfTracks.end(); ++iTrackSet,++iRetval) {
977 iRetval->second = iTrackSet->second / Etot;
986 std::vector<art::Ptr<rec::Cluster>>
991 std::vector<art::Ptr<rec::Cluster>> retval;
992 std::vector<std::pair<simb::MCParticle*,float>> fromMatch;
993 int desiredTrackId = p->
TrackId();
1000 for (std::pair<simb::MCParticle*,float>
matches : fromMatch) {
1001 if (
matches.first->TrackId() == desiredTrackId &&
1003 retval.push_back( iCluster );
1038 std::vector<simb::MCParticle*>
1041 std::vector<int> trackIdsInCluster;
1043 for (
art::Ptr iCaloHit : caloHits) {
1045 for (
CalIDE iIDE : IDEsThisHit ) trackIdsInCluster.push_back(iIDE.trackID);
1048 std::sort(trackIdsInCluster.begin(),trackIdsInCluster.end());
1050 std::unique(trackIdsInCluster.begin(),trackIdsInCluster.end());
1051 trackIdsInCluster.resize(
std::distance(trackIdsInCluster.begin(),itr));
1053 std::vector<simb::MCParticle*> retval;
1054 for (
int trackId : trackIdsInCluster) {
1056 retval.push_back(pahtay);
1067 const TLorentzVector&
position,
size_t& startTrajIndex)
const {
1070 float dr=FLT_MAX, dt=FLT_MAX;
1074 for(;startTrajIndex<mcp->NumberTrajectoryPoints(); startTrajIndex++){
1076 if( (position - mcp->Position(startTrajIndex)).Vect().Mag() < dr &&
1077 abs((position - mcp->Position(startTrajIndex)).
T()) < dt) {
1079 dr = (position - mcp->Position(startTrajIndex)).Vect().Mag();
1080 dt =
abs((position - mcp->Position(startTrajIndex)).
T());
1087 return mcp->Momentum(startTrajIndex);
std::vector< art::Ptr< rec::Cluster > > MCParticleToClusters(simb::MCParticle *const p, std::vector< art::Ptr< rec::Cluster >> const &clusters)
double fClusterFracMCP
min frac of ionization in a cluster for matching to an MCParticle
std::vector< CalIDE > CaloHitToCalIDEs(art::Ptr< rec::CaloHit > const &hit) const
std::vector< simb::MCParticle * > MCPartsInCluster(rec::Cluster *const c)
std::vector< art::Ptr< rec::Track > > MCParticleToTracks(simb::MCParticle *const p, std::vector< art::Ptr< rec::Track >> const &tracks)
std::vector< art::Ptr< rec::Hit > > const TrackToHits(rec::Track *const t)
std::vector< std::vector< std::pair< const sdp::EnergyDeposit *, float const > > > fChannelToEDepCol
convenience collections of EnergyDeposits for each channel
art::Ptr< simb::MCTruth > const ParticleToMCTruth(simb::MCParticle *const p) const
raw::CellID_t CellID() const
std::unordered_map< rec::IDNumber, std::vector< const rec::TPCCluster * > > fTrackIDToClusters
Reco track ID to track's clusters.
std::pair< float, float > Time() const
bool PointInGArTPC(TVector3 const &point) const
std::vector< const rec::TPCCluster * > const TrackToClusters(rec::Track *const t)
bool IsForebearOf(simb::MCParticle *const forebear, simb::MCParticle *const afterbear) const
const detinfo::DetectorClocks * fClocks
Detector clock information.
std::vector< art::Ptr< rec::Hit > > ParticleToHits(simb::MCParticle *const p, std::vector< art::Ptr< rec::Hit >> const &allhits, bool checkNeutrals=false) const
double fMinHitEnergyFraction
min frac of ionization a track has to count in a TPC hit
bool MCParticleCreatedCluster(simb::MCParticle *const p, rec::Cluster *const c)
std::string fRawCaloDataECALInstance
instance name for the ECAL raw hits
std::string fClusterLabel
label for ECAL cluster producing module
std::unordered_map< raw::CellID_t, std::vector< const sdp::CaloDeposit * > > fCellIDToEDepCol
convenience collections of EnergyDeposit for each cell
const geo::GeometryCore * fGeo
pointer to the geometry
gar::rec::IDNumber getIDNumber() const
static const int NoParticleId
std::unordered_map< int, int > fTrackIDToMCTruthIndex
double fTrackFracMCP
min frac of ionization in a track for matching to an MCParticle
std::unordered_map< rec::IDNumber, std::vector< art::Ptr< rec::Hit > > > fTrackIDToHits
Reco track ID to track's hits.
simb::MCParticle * FindTPCEve(simb::MCParticle *const p) const
std::vector< std::pair< simb::MCParticle *, float > > ClusterToMCParticles(rec::Cluster *const c)
std::string fClusterECALInstance
instance name for the ECAL clusters
std::pair< double, double > HitEfficiency(simb::MCParticle *const p, std::vector< art::Ptr< rec::Hit > > const &hits, std::vector< art::Ptr< rec::Hit > > const &allhits, bool weightByCharge=false) const
std::string fRawTPCDataLabel
label for TPC readout module
sim::ParticleList fParticleList
Maps MCParticle::TrackId() to same MCParticle.
std::string fTPCClusterLabel
label for TPCCluster producing module
T get(std::string const &key) const
std::pair< double, double > CaloHitEfficiency(simb::MCParticle *const p, std::vector< art::Ptr< rec::CaloHit >> const &hits, std::vector< art::Ptr< rec::CaloHit >> const &allhits, bool weightByCharge=false) const
simb::MCParticle * TrackIDToParticle(int const &id) const
std::string fTrackLabel
label for final track producing module
gar::rec::IDNumber getIDNumber() const
TLorentzVector EnergyDepositToMomentum(const int &trackID, const TLorentzVector &position, size_t &startTrajIndex) const
std::unordered_map< rec::IDNumber, std::vector< art::Ptr< rec::Hit > > > fTPCClusterIDToHits
Reco TPC cluster ID to cluster's hits.
std::pair< double, double > HitPurity(simb::MCParticle *const p, std::vector< art::Ptr< rec::Hit >> const &hits, bool weightByCharge=false) const
std::unordered_map< rec::IDNumber, std::vector< art::Ptr< rec::CaloHit > > > fClusterIDToCaloHits
Reco ECAL cluster ID to CaloHits.
std::vector< HitIDE > HitToHitIDEs(art::Ptr< rec::Hit > const &hit) const
double distance(double x1, double y1, double z1, double x2, double y2, double z2)
std::unordered_map< int, int > * fECALTrackToTPCTrack
results of previous FindTPCEve calls
virtual double TPCG4Time2TDC(double g4time) const =0
Given G4 time [ns], returns corresponding TPC electronics clock count [tdc].
bool ClusterCreatedMCParticle(simb::MCParticle *const p, rec::Cluster *const c)
simb::MCParticle * FindEve(simb::MCParticle *const p) const
Detector simulation of raw signals on wires.
std::string fG4ModuleLabel
label for geant4 module
std::vector< CalIDE > CellIDToCalIDEs(raw::CellID_t const &cellID, float const time) const
double TrackToTotalEnergy(rec::Track *const t)
std::vector< art::Ptr< rec::CaloHit > > ParticleToCaloHits(simb::MCParticle *const p, std::vector< art::Ptr< rec::CaloHit >> const &allhits) const
std::vector< HitIDE > ChannelToHitIDEs(raw::Channel_t const &channel, double const start, double const stop) const
General GArSoft Utilities.
unsigned int Channel() const
code to link reconstructed objects back to the MC truth information
bool fSplitEDeps
use weights from PRFs to break true energy deposits into channel specific contributions ...
std::string fRawCaloDataLabel
label for ECAL readout module
std::vector< std::pair< simb::MCParticle *, float > > TrackToMCParticles(rec::Track *const t)
BackTrackerCore(fhicl::ParameterSet const &pset)
std::pair< double, double > CaloHitPurity(simb::MCParticle *const p, std::vector< art::Ptr< rec::CaloHit >> const &hits, bool weightByCharge=false) const
gar::rec::IDNumber getIDNumber() const
std::vector< art::Ptr< simb::MCTruth > > fMCTruthList
all the MCTruths for the event
#define MF_LOG_WARNING(category)
std::vector< art::Ptr< rec::Hit > > const TPCClusterToHits(rec::TPCCluster *const clust)
std::vector< art::Ptr< rec::CaloHit > > const ClusterToCaloHits(rec::Cluster *const c)
double fECALtimeResolution
time resolution for hits in ECAL, nsec.
art framework interface to geometry description
double fInverseVelocity
inverse drift velocity
void ChannelToPosition(unsigned int const channel, float *const worldLoc) const
bool fDisableRebuild
for switching off backtracker's rebuild of the MCParticle tables
double fMinCaloHitEnergyFrac
min frac of ionization a track has to count in a CaloHit
cet::coded_exception< error, detail::translate > exception