diff --git a/sbndcode/BlipRecoSBND/Alg/BlipRecoAlg.cc b/sbndcode/BlipRecoSBND/Alg/BlipRecoAlg.cc index eb9a3b810..adaa261b4 100644 --- a/sbndcode/BlipRecoSBND/Alg/BlipRecoAlg.cc +++ b/sbndcode/BlipRecoSBND/Alg/BlipRecoAlg.cc @@ -32,7 +32,6 @@ namespace blip { // Loop over cryostats - std::cout<<"NCryostats: "< > sedHandle; - std::vector sedlist; - //if (evt.getByLabel(fSimDepProducer,sedHandle)){ - // art::fill_ptr_vector(sedlist, sedHandle); - // } - // -- SimChannels (usually dropped in reco) + // -- SimEnergyDeposits + art::Handle > sedHandle; + std::vector > sedlist; + if (evt.getByLabel(fSimDepProducer,sedHandle)){ + art::fill_ptr_vector(sedlist, sedHandle); + } + std::vector sIDElist; + // -- SimChannels art::Handle > simchanHandle; std::vector > simchanlist; if (evt.getByLabel(fSimChanProducer,simchanHandle)) - { + { art::fill_ptr_vector(simchanlist, simchanHandle); - //Loop over channels to get full sedlist + //Loop over channels to get full sIDElist for(int chIndex=0; chIndex wids = wireReadoutGeom->Get().ChannelToWire( (*(simchanlist[chIndex])).Channel() ); //Not sure why this is a vector, but it should have len 1 - const geo::PlaneID& planeID = wids[0].planeID(); - if(int(planeID.Plane) != fCaloPlane) continue; //only take calorimetry plane IDE values - std::vector< sim::IDE > TempChIDE = (*simchanlist[chIndex]).TrackIDsAndEnergies(0, 999999999); - for(int ideIndex=0; ideIndex wids = wireReadoutGeom->Get().ChannelToWire( (*(simchanlist[chIndex])).Channel() ); //Not sure why this is a vector, but it should have len 1 + const geo::PlaneID& planeID = wids[0].planeID(); + if(int(planeID.Plane) != fCaloPlane) continue; //only take calorimetry plane IDE values + unsigned int MaxTDCTick = 4294967294; // 1 under 32 bit unsigned int max + std::vector< sim::IDE > TempChIDE = (*simchanlist[chIndex]).TrackIDsAndEnergies(0, MaxTDCTick); + for(int ideIndex=0; ideIndex > hitHandle; std::vector > hitlist; @@ -393,8 +385,8 @@ namespace blip { // -- hits (from gaushit), these are used in truth-matching of hits art::Handle< std::vector > hitHandleGH; std::vector > hitlistGH; - if (evt.getByLabel("gaushit",hitHandleGH)) - art::fill_ptr_vector(hitlistGH, hitHandleGH); + if(evt.getByLabel("specialblipgaushit",hitHandleGH)) art::fill_ptr_vector(hitlistGH, hitHandleGH); + else if(evt.getByLabel("gaushit",hitHandleGH)) art::fill_ptr_vector(hitlistGH, hitHandleGH); // -- tracks art::Handle< std::vector > tracklistHandle; @@ -405,7 +397,7 @@ namespace blip { // -- associations art::FindManyP fmtrk(hitHandle,evt,fTrkProducer); art::FindManyP fmtrkGH(hitHandleGH,evt,fTrkProducer); - art::FindMany fmhh(hitHandleGH,evt,"gaushitTruthMatch"); + art::FindMany fmhh(hitHandleGH,evt,"blipgaushitTruthMatch"); /* //==================================================== // Update map of bad channels for this event @@ -442,7 +434,7 @@ namespace blip { //=============================================================== std::map< int, int > map_gh; // if input collection is already gaushit, this is trivial - if( fHitProducer == "gaushit" ) { + if( fHitProducer == "gaushit" || fHitProducer == "specialblipgaushit") { for(auto& h : hitlist ) map_gh[h.key()] = h.key(); // ... but if not, find the matching gaushit. There's no convenient // hit ID, so we must loop through and compare channel/time (ugh) @@ -456,8 +448,7 @@ namespace blip { break; } } - } - + } //===================================================== // Record PDG for every G4 Track ID //===================================================== @@ -526,15 +517,25 @@ namespace blip { if( plist.size() ) { pinfo.resize(plist.size()); for(size_t i = 0; i0) + { + BlipUtils::FillParticleInfo( *plist[i], pinfo[i], sedlist, fCaloPlane); + } + else //use sim::Channel -> IDE otherwise. This is usually kept but results in strange bugs. + { + BlipUtils::FillParticleInfo( *plist[i], pinfo[i], sIDElist, fCaloPlane); + } if( map_g4trkid_charge[pinfo[i].trackId] ) pinfo[i].numElectrons = (int)map_g4trkid_charge[pinfo[i].trackId]; + else pinfo[i].numElectrons = pinfo[i].depElectrons; // JACOB ADDITION Jan22, 2026 for strange channel IDE results pinfo[i].index = i; } BlipUtils::MakeTrueBlips(pinfo, trueblips); + std::cout << "True blip size after make " << trueblips.size() << std::endl; BlipUtils::MergeTrueBlips(trueblips, fTrueBlipMergeDist); + std::cout << "True blip size after merge " << trueblips.size() << std::endl; } - //======================================= // Map track IDs to the index in the vector //======================================= @@ -615,6 +616,17 @@ namespace blip { hitinfo[i].g4charge = 0; float maxQ = -9; for(size_t j=0; jPdgCode() << " and contribtues " << btvec.at(j)->numElectrons << std::endl; + } hitinfo[i].g4energy += btvec.at(j)->energy; hitinfo[i].g4charge += btvec.at(j)->numElectrons; if( btvec.at(j)->numElectrons <= maxQ ) continue; @@ -647,7 +659,7 @@ namespace blip { // find associated track - if( fHitProducer == "gaushit" && fmtrk.isValid() ) { + if( fHitProducer == "specialblipgaushit" && fmtrk.isValid() ) { if(fmtrk.at(i).size()) hitinfo[i].trkid = fmtrk.at(i)[0]->ID(); // if the hit collection didn't have associations made @@ -664,8 +676,7 @@ namespace blip { if( hitinfo[i].trkid < 0 ) nhits_untracked++; //printf(" %lu plane: %i, wire: %i, time: %i\n",i,hitinfo[i].plane,hitinfo[i].wire,int(hitinfo[i].driftTime)); - }//endloop over hits - + }//endloop over hits //for(auto& a : tpc_plane_hitsMap ) { //for(auto& b : a.second ) //std::cout<<"TPC "<Length() > fMaxHitTrkLength ) { hitIsTracked[i] = true; hitIsGood[i] = false; + Tracked++; } } + std::cout << Tracked << " hits were in tracks from pandora " << std::endl; // Filter based on hit properties. For hits that are a part of @@ -731,7 +745,6 @@ namespace blip { // Hit clustering // --------------------------------------------------- std::map>> tpc_planeclustsMap; - for(auto const& tpc_plane_hitsMap : cryo_tpc_plane_hitsMap ) { for(auto const& plane_hitsMap : tpc_plane_hitsMap.second ) { @@ -892,7 +905,6 @@ namespace blip { float _matchQDiffLimit= (fMatchQDiffLimit <= 0 ) ? std::numeric_limits::max() : fMatchQDiffLimit; float _matchMaxQRatio = (fMatchMaxQRatio <= 0 ) ? std::numeric_limits::max() : fMatchMaxQRatio; - for(auto& tpcMap : tpc_planeclustsMap ) { // loop on TPCs //std::cout @@ -1046,7 +1058,6 @@ namespace blip { for(auto& hc : hcGroup ) { hitclust[hc.ID].isMatched = true; for(auto hit : hitclust[hc.ID].HitIDs) hitinfo[hit].ismatch = true; - // Diagnostic plots for successful 3-plane matches //if( picky && hc.Plane != fCaloPlane ) { //float q1 = (float)newBlip.clusters[fCaloPlane].Charge; @@ -1096,18 +1107,26 @@ namespace blip { // if we made it this far, the blip is good! // associate this blip with the hits and clusters within it newBlip.ID = blips.size(); - blips.push_back(newBlip); for(auto& hc : hcGroup ) { hitclust[hc.ID].BlipID = newBlip.ID; for( auto& h : hc.HitIDs ) hitinfo[h].blipid = newBlip.ID; } + //BLIPS HAVE A COPY OF HITCLUSTERS NOT A POINTER + //UPDATE THE HITCLUSTER VARS THAT HAVE CHANGED SINCE CONSTRUCTION + for(int iclust=0; iclust-1){ + newBlip.clusters[iclust].BlipID = newBlip.ID; + newBlip.clusters[iclust].isMatched = true; + } + } + blips.push_back(newBlip); }//endif ncands > 0 }//endloop over caloplane ("Plane A") clusters }//endif calo plane has clusters }//endloop over TPCs - // Re-index the clusters after removing unmatched if( !keepAllClusts ) { std::vector hitclust_filt; diff --git a/sbndcode/BlipRecoSBND/BlipAna_module.cc b/sbndcode/BlipRecoSBND/BlipAna_module.cc index b9ca904e8..012a6a8fb 100644 --- a/sbndcode/BlipRecoSBND/BlipAna_module.cc +++ b/sbndcode/BlipRecoSBND/BlipAna_module.cc @@ -1326,7 +1326,6 @@ void BlipAna::analyze(const art::Event& evt) } } - if( fDebugMode ) PrintClusterInfo(clust); }//endloop over 2D hit clusters @@ -1582,6 +1581,9 @@ void BlipAna::PrintClusterInfo(const blip::HitClust& hc){ hc.EdepID, hc.isMatched ); + printf("G4 IDs contib \n"); + for(int g4ID : hc.G4IDs) printf(" %i ", g4ID); + printf("\n"); } void BlipAna::PrintBlipInfo(const blip::Blip& bl){ diff --git a/sbndcode/BlipRecoSBND/Utils/BlipUtils.cc b/sbndcode/BlipRecoSBND/Utils/BlipUtils.cc index e1b8b1b48..04345dce1 100644 --- a/sbndcode/BlipRecoSBND/Utils/BlipUtils.cc +++ b/sbndcode/BlipRecoSBND/Utils/BlipUtils.cc @@ -32,9 +32,8 @@ namespace BlipUtils { //=========================================================================== // Provided a MCParticle, calculate everything we'll need for later calculations // and save into ParticleInfo object - void FillParticleInfo( const simb::MCParticle& part, blip::ParticleInfo& pinfo, SEDVec_t& sedvec, int caloPlane){ - - // Get important info and do conversions +void FillParticleInfo( const simb::MCParticle& part, blip::ParticleInfo& pinfo){ + // Get important info and do conversions pinfo.particle = part; pinfo.trackId = part.TrackId(); pinfo.isPrimary = (int)(part.Process() == "primary"); @@ -50,17 +49,28 @@ namespace BlipUtils { pinfo.time = /*ns ->mus*/1e-3 * part.T(); pinfo.endtime = /*ns ->mus*/1e-3 * part.EndT(); pinfo.numTrajPts = part.NumberTrajectoryPoints(); - // Pathlength (in AV) and start/end point pinfo.pathLength = PathLength( part, pinfo.startPoint, pinfo.endPoint); - // Central position of trajectory pinfo.position = 0.5*(pinfo.startPoint+pinfo.endPoint); - // Energy/charge deposited by this particle, found using SimEnergyDeposits pinfo.depEnergy = 0; pinfo.depElectrons = 0; + return; +} +void FillParticleInfo( const simb::MCParticle& part, blip::ParticleInfo& pinfo, SEDVec_t& sedvec, int caloPlane){ + FillParticleInfo( part, pinfo); for(auto& sed : sedvec ) { + if( -1*sed->TrackID() == part.TrackId() || sed->TrackID() == part.TrackId() ) { + pinfo.depEnergy += sed->Energy(); + pinfo.depElectrons += sed->NumElectrons(); + } + } + return; + } + void FillParticleInfo( const simb::MCParticle& part, blip::ParticleInfo& pinfo, SIDEVec_t& sIDEvec, int caloPlane){ + FillParticleInfo( part, pinfo); + for(auto& sed : sIDEvec ) { if( -1*sed.trackID == part.TrackId() || sed.trackID == part.TrackId() ) { pinfo.depEnergy += sed.energy; pinfo.depElectrons += sed.numElectrons; @@ -99,13 +109,17 @@ namespace BlipUtils { // We want to loop through any contiguous electrons (produced // with process "eIoni") and add the energy they deposit into this blip. - if( part.NumberDaughters() ) { + if( part.NumberDaughters() ) { //particles have daughters but they must all be neutron, gamma, or one of the special processes? + int excludedDaughters=0; for(size_t j=0; j pi_serv; const sim::ParticleList& plist = pi_serv->ParticleList(); if( particleID == ancestorID ) return true; @@ -488,6 +502,7 @@ namespace BlipUtils { simb::MCParticle pM = pi_serv->TrackIdToParticle(p.Mother()); if ( pM.TrackId() == ancestorID ) { return true; } else if ( breakAtPhots == true && pM.PdgCode() == 22 ) { return false; } + else if ( breakAtNeutrons && pM.PdgCode() == 2112 ) { return false; } else if ( pM.Process() == "primary" || pM.TrackId() == 1 ) { return false; } else if ( pM.Mother() == 0 ) { return false; } else { particleID = pM.TrackId(); } diff --git a/sbndcode/BlipRecoSBND/Utils/BlipUtils.h b/sbndcode/BlipRecoSBND/Utils/BlipUtils.h index 0584c9792..59ed79735 100644 --- a/sbndcode/BlipRecoSBND/Utils/BlipUtils.h +++ b/sbndcode/BlipRecoSBND/Utils/BlipUtils.h @@ -37,8 +37,8 @@ #include "sbndcode/BlipRecoSBND/Utils/DataTypes.h" #include "TH1D.h" - -typedef std::vector SEDVec_t; +typedef std::vector> SEDVec_t; +typedef std::vector SIDEVec_t; geo::View_t kViews[3]={geo::kU, geo::kV, geo::kW}; @@ -48,7 +48,9 @@ namespace BlipUtils { // Functions related to blip reconstruction //################################################### //void InitializeDetProps(); - void FillParticleInfo(simb::MCParticle const&, blip::ParticleInfo&, SEDVec_t&, int plane=2); + void FillParticleInfo(simb::MCParticle const&, blip::ParticleInfo&, SEDVec_t&, int plane); + void FillParticleInfo(simb::MCParticle const&, blip::ParticleInfo&, SIDEVec_t&, int plane); + void FillParticleInfo( const simb::MCParticle& part, blip::ParticleInfo& pinfo); //void CalcPartDrift(blip::ParticleInfo&, int); //void CalcTotalDep(float&,int&,float&, SEDVec_t&); void MakeTrueBlips(std::vector&, std::vector&); @@ -78,7 +80,7 @@ namespace BlipUtils { //bool G4IdToMCTruth( int const, art::Ptr&); double PathLength(const simb::MCParticle&, TVector3&, TVector3&); double PathLength(const simb::MCParticle&); - bool IsAncestorOf(int, int, bool); + bool IsAncestorOf(int, int, bool, bool); double DistToBoundary(const recob::Track::Point_t&); double DistToLine(TVector3&, TVector3&, TVector3&); double DistToLine2D(TVector2&, TVector2&, TVector2&); diff --git a/sbndcode/BlipRecoSBND/blipreco_configs.fcl b/sbndcode/BlipRecoSBND/blipreco_configs.fcl index 1d4158a21..e771f2d21 100644 --- a/sbndcode/BlipRecoSBND/blipreco_configs.fcl +++ b/sbndcode/BlipRecoSBND/blipreco_configs.fcl @@ -8,7 +8,7 @@ sbnd_blipalg: HitProducer: "specialblipgaushit" #// input recob::Hits to use for blip reconstruction TrkProducer: "blipPandoraTrackCopy" #// input recob::Tracks to use for blip reconstruction GeantProducer: "largeant" #// input sim::MCParticles (getting true particle info) - SimEDepProducer: "ionandscint" #// input sim::SimEnergyDeposits (getting energy/electrons deposited) + SimEDepProducer: "ionandscint:priorSCE:G4" #// input sim::SimEnergyDeposits (getting energy/electrons deposited) SimChanProducer: "simtpc2d:simpleSC:DetSim" #// label for sim::SimChannels (getting drifted charge; optional) MaxHitTrkLength: 5.0 #// hits in trks > this length will be vetoed [cm] DoHitFiltering: false #// filter hits based on amp, width, RMS