@@ -32,7 +32,6 @@ namespace blip {
3232
3333
3434 // Loop over cryostats
35- std::cout<<" NCryostats: " <<fGeom .Ncryostats ()<<" \n " ;
3635 for (size_t cstat=0 ; cstat<fGeom .Ncryostats (); cstat++){
3736 auto const & cryoid = geo::CryostatID (cstat);
3837
@@ -41,16 +40,14 @@ namespace blip {
4140 auto const & tpcid = geo::TPCID (cryoid,tpc);
4241
4342 // Loop planes in TPC 'tpc'
44- auto const & plane0id = geo::PlaneID (cstat,tpc,0 );
45- auto const & plane0geo = wireReadoutGeom->Get ().Plane (plane0id);
43+ auto const & plane0id = geo::PlaneID (cstat,tpc,0 );
44+ auto const & plane0geo = wireReadoutGeom->Get ().Plane (plane0id);
4645 for (size_t pl=0 ; pl<wireReadoutGeom->Get ().Nplanes (tpcid); pl++){
4746 auto const & planeid = geo::PlaneID (cstat,tpc,pl);
4847 auto const & planegeo = wireReadoutGeom->Get ().Plane (planeid);
4948 kNumChannels += planegeo.Nwires ();
5049
5150 float offset = detProp.GetXTicksOffset (pl,tpc,cstat);
52- std::cout<<" CRYOSTAT " <<cstat<<" / TPC " <<tpc<<" / PLANE " <<pl<<" : " <<planegeo.Nwires ()<<" wires\n " ;
53- std::cout<<" XTicksOffset (from detProp): " <<offset<<" \n " ;
5451
5552 kXTicksOffsets [cstat][tpc][pl] = 0 ;
5653
@@ -66,12 +63,9 @@ namespace blip {
6663 auto const & tpcgeom = cryostat.TPC (tpc);
6764 auto const xyz = plane0geo.GetCenter ();
6865 const double dir ((tpcgeom.DriftSign () == geo::DriftSign::Negative) ? +1.0 : -1.0 );
69- float x_ticks_coefficient = kDriftVelocity *kTickPeriod ;
66+ float x_ticks_coefficient = kDriftVelocity *kTickPeriod ;
7067 float goofy_offset = -xyz.X () / (dir * x_ticks_coefficient);
71- std::cout<<" After geometric correction: " <<offset - goofy_offset<<" \n " ;
72-
7368 kXTicksOffsets [cstat][tpc][pl] = offset - goofy_offset;
74-
7569 } else {
7670
7771 // for the case of 2D wirecell workflow, the plane-to-plane
@@ -82,12 +76,7 @@ namespace blip {
8276 // we still want to correct for global trigger offset though:
8377 kXTicksOffsets [cstat][tpc][pl] = clockData.TriggerTime ()/kTickPeriod ;
8478
85- }
86-
87- // additional ad-hoc corrections supplied by user
88- // kXTicksOffsets[cstat][tpc][pl] += fTimeOffset[pl];
89- std::cout << " offsetting plane " << pl << " by " << fTimeOffset [pl] << " ticks " << std::endl;
90-
79+ }
9180 }
9281 }
9382 }
@@ -164,18 +153,18 @@ namespace blip {
164153 for (int i=0 ; i<kNplanes ; i++) {
165154 if ( i == fCaloPlane ) continue ;
166155 h_clust_overlap[iTPC][i] = hdir.make <TH1D>(Form (" t%i_p%i_clust_overlap" ,iTPC,i), Form (" TPC %i, Plane %i clusters;Overlap fraction" ,iTPC,i),101 ,0 ,1.01 );
167- h_clust_dt[iTPC][i] = hdir.make <TH1D>(Form (" t%i_p%i_clust_dt" ,iTPC,i), Form (" TPC %i, Plane %i clusters;dT [ticks]" ,iTPC,i),200 ,-10 ,10 );
156+ h_clust_dt[iTPC][i] = hdir.make <TH1D>(Form (" t%i_p%i_clust_dt" ,iTPC,i), Form (" TPC %i, Plane %i clusters;dT [ticks]" ,iTPC,i),200 ,-10 ,10 );
168157 h_clust_dtfrac[iTPC][i] = hdir.make <TH1D>(Form (" t%i_p%i_clust_dtfrac" ,iTPC,i), Form (" TPC %i, Plane %i clusters;Charge-weighted mean dT/RMS" ,iTPC,i),150 ,-1.5 ,1.5 );
169158
170159 h_clust_q[iTPC][i] = hdir.make <TH2D>(Form (" t%i_p%i_clust_charge" ,iTPC,i),
171160 Form (" Pre-cut, TPC %i;Plane %i cluster charge [#times10^{3} e-];Plane %i cluster charge [#times10^{3} e-]" ,iTPC,fCaloPlane ,i),
172161 qbins,0 ,qmax,qbins,0 ,qmax);
173- h_clust_q[iTPC][i]->SetOption (" colz" );
162+ h_clust_q[iTPC][i]->SetOption (" colz" );
174163
175164 h_clust_q_cut[iTPC][i] = hdir.make <TH2D>(Form (" t%i_p%i_clust_charge_cut" ,iTPC,i),
176165 Form (" Post-cut, TPC %i;Plane %i cluster charge [#times10^{3} e-];Plane %i cluster charge [#times10^{3}]" ,iTPC,fCaloPlane ,i),
177166 qbins,0 ,qmax,qbins,0 ,qmax);
178- h_clust_q_cut[iTPC][i]->SetOption (" colz" );
167+ h_clust_q_cut[iTPC][i]->SetOption (" colz" );
179168
180169 h_clust_score[iTPC][i] = hdir.make <TH1D>(Form (" t%i_p%i_clust_matchscore" ,iTPC,i), Form (" TPC %i, Plane %i clusters;Match score" ,iTPC,i),101 ,0 ,1.01 );
181170
@@ -189,7 +178,7 @@ namespace blip {
189178 h_clust_truematch_q[iTPC][i] = hdir.make <TH2D>(Form (" t%i_p%i_clust_truematch_charge" ,iTPC,i),
190179 Form (" Pre-cut, TPC %i;Plane %i cluster charge [#times10^{3} e-];Plane %i cluster charge [#times10^{3} e-]" ,iTPC,fCaloPlane ,i),
191180 qbins,0 ,qmax,qbins,0 ,qmax);
192- h_clust_truematch_q[iTPC][i]->SetOption (" colz" );
181+ h_clust_truematch_q[iTPC][i]->SetOption (" colz" );
193182
194183 h_clust_truematch_score[iTPC][i] = hdir.make <TH1D>(Form (" t%i_p%i_clust_truematch_matchscore" ,iTPC,i), Form (" TPC %i, Plane %i clusters;Match score" ,iTPC,i),101 ,0 ,1.01 );
195184
@@ -239,6 +228,7 @@ namespace blip {
239228 void BlipRecoAlg::reconfigure ( fhicl::ParameterSet const & pset ){
240229
241230 fHitProducer = pset.get <std::string> (" HitProducer" , " gaushit" );
231+ fHitTruthMatcher = pset.get <std::string> (" HitTruthMatcher" , " blipgaushitTruthMatch" );
242232 fTrkProducer = pset.get <std::string> (" TrkProducer" , " pandora" );
243233 fGeantProducer = pset.get <std::string> (" GeantProducer" , " largeant" );
244234 fSimDepProducer = pset.get <std::string> (" SimEDepProducer" , " ionandscint" );
@@ -357,31 +347,39 @@ namespace blip {
357347 if (evt.getByLabel (fGeantProducer ,pHandle))
358348 art::fill_ptr_vector (plist, pHandle);
359349
360- // -- SimEnergyDeposits
350+ // -- SimEnergyDeposits
361351 art::Handle<std::vector<sim::SimEnergyDeposit> > sedHandle;
362352 std::vector<art::Ptr<sim::SimEnergyDeposit> > sedlist;
363353 if (evt.getByLabel (fSimDepProducer ,sedHandle)){
364354 art::fill_ptr_vector (sedlist, sedHandle);
365- }
366-
367- // -- SimChannels (usually dropped in reco)
355+ }
356+ std::vector<sim::IDE > sIDElist ;
357+ // -- SimChannels
368358 art::Handle<std::vector<sim::SimChannel> > simchanHandle;
369359 std::vector<art::Ptr<sim::SimChannel> > simchanlist;
370- if (evt.getByLabel (fSimChanProducer ,simchanHandle))
360+ if (evt.getByLabel (fSimChanProducer ,simchanHandle))
361+ {
371362 art::fill_ptr_vector (simchanlist, simchanHandle);
372-
363+ // Loop over channels to get full sIDElist
364+ for (int chIndex=0 ; chIndex<int (simchanlist.size ()); chIndex++)
365+ {
366+ std::vector<geo::WireID> wids = wireReadoutGeom->Get ().ChannelToWire ( (*(simchanlist[chIndex])).Channel () ); // Not sure why this is a vector, but it should have len 1
367+ const geo::PlaneID& planeID = wids[0 ].planeID ();
368+ if (int (planeID.Plane ) != fCaloPlane ) continue ; // only take calorimetry plane IDE values
369+ unsigned int MaxTDCTick = UINT_MAX;
370+ std::vector< sim::IDE > TempChIDE = (*simchanlist[chIndex]).TrackIDsAndEnergies (0 , MaxTDCTick);
371+ for (int ideIndex=0 ; ideIndex<int (TempChIDE.size ()); ideIndex++)
372+ {
373+ sIDElist .push_back ( TempChIDE[ideIndex] ); // may need to add a &
374+ }
375+ }
376+ }
373377 // -- hits (from input module, usually track-masked subset of gaushit)
374378 art::Handle< std::vector<recob::Hit> > hitHandle;
375379 std::vector<art::Ptr<recob::Hit> > hitlist;
376380 if (evt.getByLabel (fHitProducer ,hitHandle))
377381 art::fill_ptr_vector (hitlist, hitHandle);
378382
379- // -- hits (from gaushit), these are used in truth-matching of hits
380- art::Handle< std::vector<recob::Hit> > hitHandleGH;
381- std::vector<art::Ptr<recob::Hit> > hitlistGH;
382- if (evt.getByLabel (" gaushit" ,hitHandleGH))
383- art::fill_ptr_vector (hitlistGH, hitHandleGH);
384-
385383 // -- tracks
386384 art::Handle< std::vector<recob::Track> > tracklistHandle;
387385 std::vector<art::Ptr<recob::Track> > tracklist;
@@ -390,8 +388,8 @@ namespace blip {
390388
391389 // -- associations
392390 art::FindManyP<recob::Track> fmtrk (hitHandle,evt,fTrkProducer );
393- art::FindManyP<recob::Track> fmtrkGH (hitHandleGH ,evt,fTrkProducer );
394- art::FindMany<simb::MCParticle,anab::BackTrackerHitMatchingData> fmhh (hitHandleGH ,evt," gaushitTruthMatch " );
391+ art::FindManyP<recob::Track> fmtrkGH (hitHandle ,evt,fTrkProducer );
392+ art::FindMany<simb::MCParticle, anab::BackTrackerHitMatchingData> fmhh (hitHandle ,evt,fHitTruthMatcher );
395393 /*
396394 //====================================================
397395 // Update map of bad channels for this event
@@ -427,23 +425,7 @@ namespace blip {
427425 // use gaushitTruthMatch later on)
428426 // ===============================================================
429427 std::map< int , int > map_gh;
430- // if input collection is already gaushit, this is trivial
431- if ( fHitProducer == " gaushit" ) {
432- for (auto & h : hitlist ) map_gh[h.key ()] = h.key ();
433- // ... but if not, find the matching gaushit. There's no convenient
434- // hit ID, so we must loop through and compare channel/time (ugh)
435- } else {
436- std::map<int ,std::vector<int >> map_chan_ghid;
437- for (auto & gh : hitlistGH ) map_chan_ghid[gh->Channel ()].push_back (gh.key ());
438- for (auto & h : hitlist ) {
439- for (auto & igh : map_chan_ghid[h->Channel ()]){
440- if ( hitlistGH[igh]->PeakTime () != h->PeakTime () ) continue ;
441- map_gh[h.key ()] = igh;
442- break ;
443- }
444- }
445- }
446-
428+ for (auto & h : hitlist ) map_gh[h.key ()] = h.key ();
447429 // =====================================================
448430 // Record PDG for every G4 Track ID
449431 // =====================================================
@@ -512,15 +494,23 @@ namespace blip {
512494 if ( plist.size () ) {
513495 pinfo.resize (plist.size ());
514496 for (size_t i = 0 ; i<plist.size (); i++){
515- BlipUtils::FillParticleInfo ( *plist[i], pinfo[i], sedlist, fCaloPlane );
497+ // use sim::EnergyDeposits by default. This is heavy and may be dropped
498+ if (sedlist.size ()>0 )
499+ {
500+ BlipUtils::FillParticleInfo ( *plist[i], pinfo[i], sedlist, fCaloPlane );
501+ }
502+ else // use sim::Channel -> IDE otherwise. This is usually kept but results in strange bugs.
503+ {
504+ BlipUtils::FillParticleInfo ( *plist[i], pinfo[i], sIDElist , fCaloPlane );
505+ }
516506 if ( map_g4trkid_charge[pinfo[i].trackId ] ) pinfo[i].numElectrons = (int )map_g4trkid_charge[pinfo[i].trackId ];
507+ else pinfo[i].numElectrons = pinfo[i].depElectrons ; // JACOB ADDITION Jan22, 2026 for strange channel IDE results
517508 pinfo[i].index = i;
518509 }
519510 BlipUtils::MakeTrueBlips (pinfo, trueblips);
520511 BlipUtils::MergeTrueBlips (trueblips, fTrueBlipMergeDist );
521512 }
522513
523-
524514 // =======================================
525515 // Map track IDs to the index in the vector
526516 // =======================================
@@ -633,14 +623,8 @@ namespace blip {
633623
634624
635625 // find associated track
636- if ( fHitProducer == " gaushit " && fmtrk.isValid () ) {
626+ if ( fmtrk.isValid () ) {
637627 if (fmtrk.at (i).size ()) hitinfo[i].trkid = fmtrk.at (i)[0 ]->ID ();
638-
639- // if the hit collection didn't have associations made
640- // to the tracks, try gaushit instead
641- } else if ( fmtrkGH.isValid () && map_gh.size () ) {
642- int gi = map_gh[i];
643- if (fmtrkGH.at (gi).size ()) hitinfo[i].trkid = fmtrkGH.at (gi)[0 ]->ID ();
644628 }
645629
646630 // add to the map
@@ -650,8 +634,7 @@ namespace blip {
650634 if ( hitinfo[i].trkid < 0 ) nhits_untracked++;
651635 // printf(" %lu plane: %i, wire: %i, time: %i\n",i,hitinfo[i].plane,hitinfo[i].wire,int(hitinfo[i].driftTime));
652636
653- }// endloop over hits
654-
637+ }// endloop over hits
655638 // for(auto& a : tpc_plane_hitsMap ) {
656639 // for(auto& b : a.second )
657640 // std::cout<<"TPC "<<a.first<<", plane "<<b.first<<": "<<b.second.size()<<" hits\n";
@@ -676,6 +659,7 @@ namespace blip {
676659
677660
678661 // Basic track inclusion cut: exclude hits that were tracked
662+ int Tracked=0 ;
679663 for (size_t i=0 ; i<hitlist.size (); i++){
680664 if ( hitinfo[i].trkid < 0 ) continue ;
681665 auto it = map_trkid_index.find (hitinfo[i].trkid );
@@ -684,9 +668,9 @@ namespace blip {
684668 if ( tracklist[trkindex]->Length () > fMaxHitTrkLength ) {
685669 hitIsTracked[i] = true ;
686670 hitIsGood[i] = false ;
671+ Tracked++;
687672 }
688- }
689-
673+ }
690674
691675 // Filter based on hit properties. For hits that are a part of
692676 // multi-gaussian fits (multiplicity > 1), need to re-think this.
@@ -717,7 +701,6 @@ namespace blip {
717701 // Hit clustering
718702 // ---------------------------------------------------
719703 std::map<int ,std::map<int ,std::vector<int >>> tpc_planeclustsMap;
720-
721704 for (auto const & tpc_plane_hitsMap : cryo_tpc_plane_hitsMap ) {
722705
723706 for (auto const & plane_hitsMap : tpc_plane_hitsMap.second ) {
@@ -878,7 +861,6 @@ namespace blip {
878861
879862 float _matchQDiffLimit= (fMatchQDiffLimit <= 0 ) ? std::numeric_limits<float >::max () : fMatchQDiffLimit ;
880863 float _matchMaxQRatio = (fMatchMaxQRatio <= 0 ) ? std::numeric_limits<float >::max () : fMatchMaxQRatio ;
881-
882864 for (auto & tpcMap : tpc_planeclustsMap ) { // loop on TPCs
883865
884866 // std::cout
@@ -921,15 +903,15 @@ namespace blip {
921903 // Check that the two central wires intersect
922904 // *******************************************
923905 double y, z;
924- geo::Point_t intsec_p;
925- std::vector<geo::WireID> A_wireids = wireReadoutGeom->Get ().ChannelToWire ((unsigned int )hcA.CenterChan );
926- std::vector<geo::WireID> B_wireids = wireReadoutGeom->Get ().ChannelToWire ((unsigned int )hcB.CenterChan );
906+ geo::Point_t intsec_p;
907+ std::vector<geo::WireID> A_wireids = wireReadoutGeom->Get ().ChannelToWire ((unsigned int )hcA.CenterChan );
908+ std::vector<geo::WireID> B_wireids = wireReadoutGeom->Get ().ChannelToWire ((unsigned int )hcB.CenterChan );
927909
928- if ( !wireReadoutGeom->Get ().WireIDsIntersect (A_wireids.at (0 ),B_wireids.at (0 ),intsec_p)) continue ;
929- // Save intersect location, so we don't have to
910+ if ( !wireReadoutGeom->Get ().WireIDsIntersect (A_wireids.at (0 ),B_wireids.at (0 ),intsec_p)) continue ;
911+ // Save intersect location, so we don't have to
930912 // make another call to the Geometry service later
931- y = intsec_p.Y ();
932- z = intsec_p.Z ();
913+ y = intsec_p.Y ();
914+ z = intsec_p.Z ();
933915 TVector3 xloc (0 ,y,z);
934916 hcA.IntersectLocations [hcB.ID ] = xloc;
935917 hcB.IntersectLocations [hcA.ID ] = xloc;
@@ -1032,7 +1014,6 @@ namespace blip {
10321014 for (auto & hc : hcGroup ) {
10331015 hitclust[hc.ID ].isMatched = true ;
10341016 for (auto hit : hitclust[hc.ID ].HitIDs ) hitinfo[hit].ismatch = true ;
1035-
10361017 // Diagnostic plots for successful 3-plane matches
10371018 // if( picky && hc.Plane != fCaloPlane ) {
10381019 // float q1 = (float)newBlip.clusters[fCaloPlane].Charge;
@@ -1082,18 +1063,26 @@ namespace blip {
10821063 // if we made it this far, the blip is good!
10831064 // associate this blip with the hits and clusters within it
10841065 newBlip.ID = blips.size ();
1085- blips.push_back (newBlip);
10861066 for (auto & hc : hcGroup ) {
10871067 hitclust[hc.ID ].BlipID = newBlip.ID ;
10881068 for ( auto & h : hc.HitIDs ) hitinfo[h].blipid = newBlip.ID ;
10891069 }
1070+ // BLIPS HAVE A COPY OF HITCLUSTERS NOT A POINTER
1071+ // UPDATE THE HITCLUSTER VARS THAT HAVE CHANGED SINCE CONSTRUCTION
1072+ for (int iclust=0 ; iclust<int (sizeof (newBlip.clusters )/sizeof (newBlip.clusters [0 ])); iclust++)
1073+ {
1074+ if (newBlip.clusters [iclust].ID >-1 ){
1075+ newBlip.clusters [iclust].BlipID = newBlip.ID ;
1076+ newBlip.clusters [iclust].isMatched = true ;
1077+ }
1078+ }
1079+ blips.push_back (newBlip);
10901080
10911081
10921082 }// endif ncands > 0
10931083 }// endloop over caloplane ("Plane A") clusters
10941084 }// endif calo plane has clusters
10951085 }// endloop over TPCs
1096-
10971086 // Re-index the clusters after removing unmatched
10981087 if ( !keepAllClusts ) {
10991088 std::vector<blip::HitClust> hitclust_filt;
0 commit comments