From 542d2f53748ac2646c619e51a8a342b2c54fe9c5 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Thu, 3 Apr 2025 11:56:51 -0500 Subject: [PATCH 01/31] Add CRTBlob producer --- sbndcode/CRT/CRTReco/CMakeLists.txt | 6 + .../CRT/CRTReco/CRTBlobProducer_module.cc | 219 ++++++++++++++++++ .../CRT/CRTReco/crtrecoproducers_sbnd.fcl | 11 + 3 files changed, 236 insertions(+) create mode 100644 sbndcode/CRT/CRTReco/CRTBlobProducer_module.cc diff --git a/sbndcode/CRT/CRTReco/CMakeLists.txt b/sbndcode/CRT/CRTReco/CMakeLists.txt index 3ea86c28c..f17015c69 100644 --- a/sbndcode/CRT/CRTReco/CMakeLists.txt +++ b/sbndcode/CRT/CRTReco/CMakeLists.txt @@ -37,4 +37,10 @@ simple_plugin( Eigen3::Eigen ) +simple_plugin( + CRTBlobProducer module + sbnobj::SBND_CRT + sbndcode_GeoWrappers +) + install_fhicl() diff --git a/sbndcode/CRT/CRTReco/CRTBlobProducer_module.cc b/sbndcode/CRT/CRTReco/CRTBlobProducer_module.cc new file mode 100644 index 000000000..0ea91e935 --- /dev/null +++ b/sbndcode/CRT/CRTReco/CRTBlobProducer_module.cc @@ -0,0 +1,219 @@ +//////////////////////////////////////////////////////////////////////// +// Class: CRTBlobProducer +// Plugin Type: producer +// File: CRTBlobProducer_module.cc +// +// Author: Henry Lay (h.lay@sheffield.ac.uk) +//////////////////////////////////////////////////////////////////////// + +#include "art/Framework/Core/EDProducer.h" +#include "art/Framework/Core/ModuleMacros.h" +#include "art/Framework/Principal/Event.h" +#include "art/Framework/Principal/Handle.h" +#include "art/Framework/Principal/Run.h" +#include "art/Framework/Principal/SubRun.h" +#include "canvas/Utilities/InputTag.h" +#include "canvas/Persistency/Common/FindOneP.h" +#include "fhiclcpp/ParameterSet.h" +#include "messagefacility/MessageLogger/MessageLogger.h" + +#include "lardata/Utilities/AssociationUtil.h" + +#include "sbnobj/SBND/CRT/CRTCluster.hh" +#include "sbnobj/SBND/CRT/CRTSpacePoint.hh" +#include "sbnobj/SBND/CRT/CRTBlob.hh" + +#include + +namespace sbnd::crt { + class CRTBlobProducer; +} + +class sbnd::crt::CRTBlobProducer : public art::EDProducer { +public: + explicit CRTBlobProducer(fhicl::ParameterSet const& p); + + CRTBlobProducer(CRTBlobProducer const&) = delete; + CRTBlobProducer(CRTBlobProducer&&) = delete; + CRTBlobProducer& operator=(CRTBlobProducer const&) = delete; + CRTBlobProducer& operator=(CRTBlobProducer&&) = delete; + + void produce(art::Event& e) override; + + void OrderSpacePoints(std::vector> &spacePointVec, const art::FindOneP &spacePointsToCluster); + + std::vector>> CreateBlobCandidates(const std::vector> &spacePointVec, + const art::FindOneP &spacePointsToCluster); + + void TimeErrorCalculator(const std::vector ×, double &mean, double &err); + + void OrderBlobCandidates(std::vector>> &blobCandidates); + + std::vector>> ChoseBlobs(std::vector>> &blobCandidates); + +private: + + std::string fCRTSpacePointModuleLabel; + double fCoincidenceTimeRequirement; + bool fUseTs0; +}; + + +sbnd::crt::CRTBlobProducer::CRTBlobProducer(fhicl::ParameterSet const& p) + : EDProducer{p} + , fCRTSpacePointModuleLabel(p.get("CRTSpacePointModuleLabel")) + , fCoincidenceTimeRequirement(p.get("CoincidenceTimeRequirement")) + , fUseTs0(p.get("UseTs0")) +{ + produces>(); + produces>(); +} + +void sbnd::crt::CRTBlobProducer::produce(art::Event& e) +{ + auto blobVec = std::make_unique>(); + auto blobSpacePointAssn = std::make_unique>(); + + art::Handle> CRTSpacePointHandle; + e.getByLabel(fCRTSpacePointModuleLabel, CRTSpacePointHandle); + + std::vector> CRTSpacePointVec; + art::fill_ptr_vector(CRTSpacePointVec, CRTSpacePointHandle); + + art::FindOneP spacePointsToCluster(CRTSpacePointHandle, e, fCRTSpacePointModuleLabel); + + OrderSpacePoints(CRTSpacePointVec, spacePointsToCluster); + + std::vector>> blobCandidates = CreateBlobCandidates(CRTSpacePointVec, spacePointsToCluster); + + OrderBlobCandidates(blobCandidates); + + std::vector>> chosenBlobs = ChoseBlobs(blobCandidates); + + for(auto const& [blob, spIDs] : chosenBlobs) + { + blobVec->push_back(blob); + + for(auto const& spID : spIDs) + util::CreateAssn(*this, e, *blobVec, CRTSpacePointVec[spID], *blobSpacePointAssn); + } + + e.put(std::move(blobVec)); + e.put(std::move(blobSpacePointAssn)); +} + +void sbnd::crt::CRTBlobProducer::OrderSpacePoints(std::vector> &spacePointVec, const art::FindOneP &spacePointsToCluster) +{ + std::sort(spacePointVec.begin(), spacePointVec.end(), + [&](const art::Ptr &a, const art::Ptr &b) -> bool { + if(fUseTs0) + return a->Ts0() < b->Ts0(); + else + return a->Ts1() < b->Ts1(); + }); +} + +std::vector>> sbnd::crt::CRTBlobProducer::CreateBlobCandidates(const std::vector> &spacePointVec, + const art::FindOneP &spacePointsToCluster) +{ + std::vector>> candidates; + + for(unsigned i = 0; i < spacePointVec.size(); ++i) + { + const art::Ptr primarySpacePoint = spacePointVec[i]; + const art::Ptr primaryCluster = spacePointsToCluster.at(primarySpacePoint.key()); + + std::set used_spacepoints = { i }; + std::vector t0s = { primarySpacePoint->Ts0() }; + std::vector t1s = { primarySpacePoint->Ts1() }; + std::vector pes = { primarySpacePoint->PE() }; + + std::map taggers; + for(int i = 0; i < 7; ++i) + taggers[(CRTTagger)i] = 0; + ++taggers[primaryCluster->Tagger()]; + + for(unsigned ii = i+1; ii < spacePointVec.size(); ++ii) + { + const art::Ptr secondarySpacePoint = spacePointVec[ii]; + const art::Ptr secondaryCluster = spacePointsToCluster.at(secondarySpacePoint.key()); + + const double tdiff_prim_sec = fUseTs0 ? secondarySpacePoint->Ts0() - primarySpacePoint->Ts0() : secondarySpacePoint->Ts1() - primarySpacePoint->Ts1(); + + if(tdiff_prim_sec > fCoincidenceTimeRequirement) + break; + + used_spacepoints.insert(ii); + t0s.push_back(secondarySpacePoint->Ts0()); + t1s.push_back(secondarySpacePoint->Ts1()); + pes.push_back(secondarySpacePoint->PE()); + ++taggers[secondaryCluster->Tagger()]; + } + + double t0, et0; + TimeErrorCalculator(t0s, t0, et0); + + double t1, et1; + TimeErrorCalculator(t1s, t1, et1); + + const double pe = std::accumulate(pes.begin(), pes.end(), 0.); + + const CRTBlob blob(t0, et0, t1, et1, pe, taggers); + + candidates.emplace_back(blob, used_spacepoints); + } + + return candidates; +} + +void sbnd::crt::CRTBlobProducer::TimeErrorCalculator(const std::vector ×, double &mean, double &err) +{ + double sum = 0.; + for(auto const &time : times) + sum += time; + + mean = sum / times.size(); + + double summed_var = 0.; + for(auto const &time : times) + summed_var += std::pow((time - mean), 2); + + err = std::sqrt(summed_var / (times.size() - 1)); +} + +void sbnd::crt::CRTBlobProducer::OrderBlobCandidates(std::vector>> &blobCandidates) +{ + std::sort(blobCandidates.begin(), blobCandidates.end(), + [&](const std::pair> &a, const std::pair> &b) -> bool { + return fUseTs0 ? a.first.Ts0Err() < b.first.Ts0Err() : a.first.Ts1Err() < b.first.Ts1Err(); + }); +} + +std::vector>> sbnd::crt::CRTBlobProducer::ChoseBlobs(std::vector>> &blobCandidates) +{ + std::vector>> chosenBlobs; + + std::set used; + + for(auto const& [blob, spIDs] : blobCandidates) + { + bool keep = true; + for(auto const& spID : spIDs) + { + if(used.count(spID) != 0) + keep = false; + } + + if(keep) + { + chosenBlobs.emplace_back(blob, spIDs); + + for(auto const& spID : spIDs) + used.insert(spID); + } + } + + return chosenBlobs; +} + +DEFINE_ART_MODULE(sbnd::crt::CRTBlobProducer) diff --git a/sbndcode/CRT/CRTReco/crtrecoproducers_sbnd.fcl b/sbndcode/CRT/CRTReco/crtrecoproducers_sbnd.fcl index 9aa8e2a26..0b4ca1c3c 100644 --- a/sbndcode/CRT/CRTReco/crtrecoproducers_sbnd.fcl +++ b/sbndcode/CRT/CRTReco/crtrecoproducers_sbnd.fcl @@ -78,4 +78,15 @@ crttrackproducer_data_sbnd: @local::crttrackproducer_sbnd crttrackproducer_data_sbnd.UseTs0: true crttrackproducer_data_sbnd.MaskedTaggers: [ ] +crtblobproducer_sbnd: +{ + CRTSpacePointModuleLabel: "crtspacepoints" + CoincidenceTimeRequirement: 100. + UseTs0: false + module_type: "CRTBlobProducer" +} + +crtblobproducer_data_sbnd: @local::crtblobproducer_sbnd +crtblobproducer_data_sbnd.UseTs0: true + END_PROLOG From 5811843ff090310ea0a9187b259d36d9b9077003 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Thu, 3 Apr 2025 11:58:11 -0500 Subject: [PATCH 02/31] Add blobs to CRT only fcls --- sbndcode/CRT/CRTReco/run_crtblobreco.fcl | 38 +++++++++++++++++++++++ sbndcode/CRT/CRTReco/run_crtreco.fcl | 3 +- sbndcode/CRT/CRTReco/run_crtreco_data.fcl | 1 + sbndcode/CRT/CRTReco/run_crtrecoana.fcl | 3 +- 4 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 sbndcode/CRT/CRTReco/run_crtblobreco.fcl diff --git a/sbndcode/CRT/CRTReco/run_crtblobreco.fcl b/sbndcode/CRT/CRTReco/run_crtblobreco.fcl new file mode 100644 index 000000000..7d46331d2 --- /dev/null +++ b/sbndcode/CRT/CRTReco/run_crtblobreco.fcl @@ -0,0 +1,38 @@ +#include "services_sbnd.fcl" +#include "rootoutput_sbnd.fcl" +#include "crtrecoproducers_sbnd.fcl" + +process_name: CRTBlobReco + +services: +{ + @table::sbnd_services +} + +source: +{ + module_type: RootInput +} + +outputs: +{ + out1: + { + @table::sbnd_rootoutput + dataTier: "reconstructed" + } +} + +physics: +{ + producers: + { + crtblobs: @local::crtblobproducer_sbnd + } + + reco: [ crtblobs ] + stream1: [ out1 ] + + trigger_paths: [ reco ] + end_paths: [ stream1 ] +} diff --git a/sbndcode/CRT/CRTReco/run_crtreco.fcl b/sbndcode/CRT/CRTReco/run_crtreco.fcl index 3a625c1b7..585238a0a 100644 --- a/sbndcode/CRT/CRTReco/run_crtreco.fcl +++ b/sbndcode/CRT/CRTReco/run_crtreco.fcl @@ -33,9 +33,10 @@ physics: crtclustering: @local::crtclusterproducer_sbnd crtspacepoints: @local::crtspacepointproducer_sbnd crttracks: @local::crttrackproducer_sbnd + crtblobs: @local::crtblobproducer_sbnd } - reco: [ crtstrips, crtclustering, crtspacepoints, crttracks ] + reco: [ crtstrips, crtclustering, crtspacepoints, crttracks, crtblobs ] stream1: [ out1 ] trigger_paths: [ reco ] diff --git a/sbndcode/CRT/CRTReco/run_crtreco_data.fcl b/sbndcode/CRT/CRTReco/run_crtreco_data.fcl index 2493c9b33..9e179b108 100644 --- a/sbndcode/CRT/CRTReco/run_crtreco_data.fcl +++ b/sbndcode/CRT/CRTReco/run_crtreco_data.fcl @@ -10,6 +10,7 @@ physics.producers.crtstrips: @local::crtstriphitproducer_data_sbnd physics.producers.crtclustering: @local::crtclusterproducer_data_sbnd physics.producers.crtspacepoints: @local::crtspacepointproducer_data_sbnd physics.producers.crttracks: @local::crttrackproducer_data_sbnd +physics.producers.crtblobs: @local::crtblobproducer_data_sbnd outputs.out1.outputCommands: [ "keep *_*_*_*", "drop *_daq_*_*", diff --git a/sbndcode/CRT/CRTReco/run_crtrecoana.fcl b/sbndcode/CRT/CRTReco/run_crtrecoana.fcl index 983502ca8..6e9f6d8c8 100644 --- a/sbndcode/CRT/CRTReco/run_crtrecoana.fcl +++ b/sbndcode/CRT/CRTReco/run_crtrecoana.fcl @@ -37,6 +37,7 @@ physics: crtclustering: @local::crtclusterproducer_sbnd crtspacepoints: @local::crtspacepointproducer_sbnd crttracks: @local::crttrackproducer_sbnd + crtblobs: @local::crtblobproducer_sbnd } analyzers: @@ -44,7 +45,7 @@ physics: crtana: @local::crtana_sbnd } - reco: [ crtstrips, crtclustering, crtspacepoints, crttracks ] + reco: [ crtstrips, crtclustering, crtspacepoints, crttracks, crtblobs ] ana: [ crtana ] stream1: [ out1 ] From 8dba4972baeb079d312346e1634ce81f96b42a35 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Mon, 16 Feb 2026 05:57:59 -0600 Subject: [PATCH 03/31] Modernise CMakeLists --- sbndcode/CRT/CRTReco/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbndcode/CRT/CRTReco/CMakeLists.txt b/sbndcode/CRT/CRTReco/CMakeLists.txt index f17015c69..ad5cfc7cb 100644 --- a/sbndcode/CRT/CRTReco/CMakeLists.txt +++ b/sbndcode/CRT/CRTReco/CMakeLists.txt @@ -39,8 +39,8 @@ simple_plugin( simple_plugin( CRTBlobProducer module + lardata::Utilities sbnobj::SBND_CRT - sbndcode_GeoWrappers ) install_fhicl() From ae474af618dae9a371e030e97641d022ebf64ad9 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Tue, 17 Feb 2026 10:58:08 -0600 Subject: [PATCH 04/31] Add option for blob branches in CRTAnalysis module --- sbndcode/CRT/CRTAna/CRTAnalysis_module.cc | 78 ++++++++++++++++++++++- 1 file changed, 75 insertions(+), 3 deletions(-) diff --git a/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc b/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc index 948d3fd4c..29f6614c9 100644 --- a/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc +++ b/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc @@ -33,6 +33,7 @@ #include "sbnobj/SBND/CRT/CRTCluster.hh" #include "sbnobj/SBND/CRT/CRTSpacePoint.hh" #include "sbnobj/SBND/CRT/CRTTrack.hh" +#include "sbnobj/SBND/CRT/CRTBlob.hh" #include "sbnobj/SBND/Timing/DAQTimestamp.hh" #include "sbndcode/Geometry/GeometryWrappers/CRTGeoService.h" @@ -87,6 +88,8 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { void AnalyseCRTTracks(const art::Event &e, const std::vector> &CRTTrackVec, const art::FindManyP &tracksToSpacePoints, const art::FindOneP &spacePointsToClusters, const art::FindManyP &clustersToStripHits); + void AnalyseCRTBlobs(std::vector> &CRTBlobVec); + void AnalyseTPCMatching(const art::Event &e, const art::Handle> &TPCTrackHandle, const art::Handle> &CRTSpacePointHandle, const art::Handle> &CRTClusterHandle, const art::Handle> &PFPHandle, @@ -104,10 +107,10 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { CRTBackTrackerAlg fCRTBackTrackerAlg; std::string fMCParticleModuleLabel, fSimDepositModuleLabel, fFEBDataModuleLabel, fCRTStripHitModuleLabel, - fCRTClusterModuleLabel, fCRTSpacePointModuleLabel, fCRTTrackModuleLabel, fTPCTrackModuleLabel, + fCRTClusterModuleLabel, fCRTSpacePointModuleLabel, fCRTTrackModuleLabel, fCRTBlobModuleLabel, fTPCTrackModuleLabel, fCRTSpacePointMatchingModuleLabel, fCRTTrackMatchingModuleLabel, fPFPModuleLabel, fPTBModuleLabel, fTDCModuleLabel, fTimingReferenceModuleLabel; - bool fDebug, fDataMode, fNoTPC, fHasPTB, fHasTDC, fTruthMatch; + bool fDebug, fDataMode, fNoTPC, fHasPTB, fHasTDC, fHasBlobs, fTruthMatch; //! Adding some of the reco parameters to save corrections double fPEAttenuation, fTimeWalkNorm, fTimeWalkScale, fPropDelay; @@ -296,6 +299,16 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { std::vector _tr_truth_theta; std::vector _tr_truth_phi; + // crt blob information + std::vector _bl_ts0; + std::vector _bl_ets0; + std::vector _bl_ts1; + std::vector _bl_ets1; + std::vector _bl_pe; + std::vector _bl_nsps; + std::vector> _bl_nsps_per_tagger; + + // tpc track information (including crt matching) std::vector _tpc_start_x; std::vector _tpc_start_y; std::vector _tpc_start_z; @@ -341,12 +354,14 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { std::vector _tpc_tr_end_z; std::vector _tpc_tr_score; + // ptb information (trigger board) std::vector _ptb_hlt_trigger; std::vector _ptb_hlt_timestamp; std::vector _ptb_llt_trigger; std::vector _ptb_llt_timestamp; + // spec tdc information (timing board) std::vector _tdc_channel; std::vector _tdc_timestamp; std::vector _tdc_offset; @@ -364,6 +379,7 @@ sbnd::crt::CRTAnalysis::CRTAnalysis(fhicl::ParameterSet const& p) fCRTClusterModuleLabel = p.get("CRTClusterModuleLabel", "crtclustering"); fCRTSpacePointModuleLabel = p.get("CRTSpacePointModuleLabel", "crtspacepoints"); fCRTTrackModuleLabel = p.get("CRTTrackModuleLabel", "crttracks"); + fCRTBlobModuleLabel = p.get("CRTBlobModuleLabel", "crtblobs"); fTPCTrackModuleLabel = p.get("TPCTrackModuleLabel", "pandoraSCETrack"); fCRTSpacePointMatchingModuleLabel = p.get("CRTSpacePointMatchingModuleLabel", "crtspacepointmatchingSCE"); fCRTTrackMatchingModuleLabel = p.get("CRTTrackMatchingModuleLabel", "crttrackmatchingSCE"); @@ -376,8 +392,8 @@ sbnd::crt::CRTAnalysis::CRTAnalysis(fhicl::ParameterSet const& p) fNoTPC = p.get("NoTPC", false); fHasPTB = p.get("HasPTB", false); fHasTDC = p.get("HasTDC", false); + fHasBlobs = p.get("HasBlobs", false); fTruthMatch = p.get("TruthMatch", true); - //! Adding some of the reco parameters to save corrections fPEAttenuation = p.get("PEAttenuation", 1.0); fTimeWalkNorm = p.get("TimeWalkNorm", 0.0); fTimeWalkScale = p.get("TimeWalkScale", 0.0); @@ -578,6 +594,17 @@ sbnd::crt::CRTAnalysis::CRTAnalysis(fhicl::ParameterSet const& p) fTree->Branch("tr_truth_phi", "std::vector", &_tr_truth_phi); } + if(fHasBlobs) + { + fTree->Branch("bl_ts0", "std::vector", &_bl_ts0); + fTree->Branch("bl_ets0", "std::vector", &_bl_ets0); + fTree->Branch("bl_ts1", "std::vector", &_bl_ts1); + fTree->Branch("bl_ets1", "std::vector", &_bl_ets1); + fTree->Branch("bl_pe", "std::vector", &_bl_pe); + fTree->Branch("bl_nsps", "std::vector", &_bl_nsps); + fTree->Branch("bl_nsps_per_tagger", "std::vector>", &_bl_nsps_per_tagger); + } + if(!fNoTPC) { fTree->Branch("tpc_start_x", "std::vector", &_tpc_start_x); @@ -835,6 +862,23 @@ void sbnd::crt::CRTAnalysis::analyze(art::Event const& e) // Fill CRTTrack variables AnalyseCRTTracks(e, CRTTrackVec, tracksToSpacePoints, spacepointsToClusters, clustersToStripHits); + if(fHasBlobs) + { + // Get CRTBlobs + art::Handle> CRTBlobHandle; + e.getByLabel(fCRTBlobModuleLabel, CRTBlobHandle); + if(!CRTBlobHandle.isValid()){ + std::cout << "CRTBlob product " << fCRTBlobModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + + std::vector> CRTBlobVec; + art::fill_ptr_vector(CRTBlobVec, CRTBlobHandle); + + // Fill CRTBlob variables + AnalyseCRTBlobs(CRTBlobVec); + } + if(fNoTPC) { // Fill the Tree @@ -1585,6 +1629,34 @@ void sbnd::crt::CRTAnalysis::AnalyseCRTTracks(const art::Event &e, const std::ve } } +void sbnd::crt::CRTAnalysis::AnalyseCRTBlobs(std::vector> &CRTBlobVec) +{ + const unsigned nBlobs = CRTBlobVec.size(); + + _bl_ts0.resize(nBlobs); + _bl_ets0.resize(nBlobs); + _bl_ts1.resize(nBlobs); + _bl_ets1.resize(nBlobs); + _bl_pe.resize(nBlobs); + _bl_nsps.resize(nBlobs); + _bl_nsps_per_tagger.resize(nBlobs, std::vector(7)); + + for(unsigned i = 0; i < nBlobs; ++i) + { + const auto blob = CRTBlobVec[i]; + + _bl_ts0[i] = blob->Ts0(); + _bl_ets0[i] = blob->Ts0Err(); + _bl_ts1[i] = blob->Ts1(); + _bl_ets1[i] = blob->Ts1Err(); + _bl_pe[i] = blob->PE(); + _bl_nsps[i] = blob->TotalSpacePoints(); + + for(unsigned j = 0; j < 7; ++j) + _bl_nsps_per_tagger[i][j] = blob->SpacePointsInTagger((CRTTagger)j); + } +} + void sbnd::crt::CRTAnalysis::AnalyseTPCMatching(const art::Event &e, const art::Handle> &TPCTrackHandle, const art::Handle> &CRTSpacePointHandle, const art::Handle> &CRTClusterHandle, const art::Handle> &PFPHandle, From 8e22b42767fbac8142564403f919d28c5053cbbd Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Tue, 17 Feb 2026 11:01:51 -0600 Subject: [PATCH 05/31] Clean up fcls --- sbndcode/CRT/CRTReco/run_crtrecoana.fcl | 3 +++ sbndcode/CRT/CRTReco/run_crtrecoana_data.fcl | 3 +++ sbndcode/CRT/CRTReco/run_crtrecoana_notpc.fcl | 3 --- sbndcode/CRT/CRTReco/run_crtrecoana_notpc_no_flat_tracks.fcl | 3 --- 4 files changed, 6 insertions(+), 6 deletions(-) delete mode 100644 sbndcode/CRT/CRTReco/run_crtrecoana_notpc.fcl delete mode 100644 sbndcode/CRT/CRTReco/run_crtrecoana_notpc_no_flat_tracks.fcl diff --git a/sbndcode/CRT/CRTReco/run_crtrecoana.fcl b/sbndcode/CRT/CRTReco/run_crtrecoana.fcl index 6e9f6d8c8..15a37b22d 100644 --- a/sbndcode/CRT/CRTReco/run_crtrecoana.fcl +++ b/sbndcode/CRT/CRTReco/run_crtrecoana.fcl @@ -52,3 +52,6 @@ physics: trigger_paths: [ reco ] end_paths: [ ana, stream1 ] } + +physics.analyzers.crtana.HasBlobs: true +physics.analyzers.crtana.NoTPC: true diff --git a/sbndcode/CRT/CRTReco/run_crtrecoana_data.fcl b/sbndcode/CRT/CRTReco/run_crtrecoana_data.fcl index 11bbc53cf..c249a7d99 100644 --- a/sbndcode/CRT/CRTReco/run_crtrecoana_data.fcl +++ b/sbndcode/CRT/CRTReco/run_crtrecoana_data.fcl @@ -10,5 +10,8 @@ physics.producers.crtstrips: @local::crtstriphitproducer_data_sbnd physics.producers.crtclustering: @local::crtclusterproducer_data_sbnd physics.producers.crtspacepoints: @local::crtspacepointproducer_data_sbnd physics.producers.crttracks: @local::crttrackproducer_data_sbnd +physics.producers.crtblobs: @local::crtblobproducer_data_sbnd physics.analyzers.crtana: @local::crtana_data_sbnd +physics.analyzers.crtana.HasBlobs: true +physics.analyzers.crtana.NoTPC: true diff --git a/sbndcode/CRT/CRTReco/run_crtrecoana_notpc.fcl b/sbndcode/CRT/CRTReco/run_crtrecoana_notpc.fcl deleted file mode 100644 index 621b8d45a..000000000 --- a/sbndcode/CRT/CRTReco/run_crtrecoana_notpc.fcl +++ /dev/null @@ -1,3 +0,0 @@ -#include "run_crtrecoana.fcl" - -physics.analyzers.crtana.NoTPC: true diff --git a/sbndcode/CRT/CRTReco/run_crtrecoana_notpc_no_flat_tracks.fcl b/sbndcode/CRT/CRTReco/run_crtrecoana_notpc_no_flat_tracks.fcl deleted file mode 100644 index 74a8504d7..000000000 --- a/sbndcode/CRT/CRTReco/run_crtrecoana_notpc_no_flat_tracks.fcl +++ /dev/null @@ -1,3 +0,0 @@ -#include "run_crtrecoana_notpc.fcl" - -physics.producers.crttracks.MaskedTaggers: [ 0 ] From 3ba37b53cd3e17178d3f7e09adfe0c832bcea61a Mon Sep 17 00:00:00 2001 From: nathanielerowe <70993723+nathanielerowe@users.noreply.github.com> Date: Thu, 19 Feb 2026 08:26:08 -0600 Subject: [PATCH 06/31] Update sbncode version to v10_14_02_03 --- ups/product_deps | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ups/product_deps b/ups/product_deps index e21a2f2aa..38979aeb7 100644 --- a/ups/product_deps +++ b/ups/product_deps @@ -253,7 +253,7 @@ wpdir product_dir wire-cell-cfg # #################################### product version qual flags -sbncode v10_14_02_02 - +sbncode v10_14_02_03 - cetmodules v3_24_01 - only_for_build sbnd_data v01_42_00 - sbndutil v10_06_01 - optional From 029de7c21d910f5c27065335096cf609dd0b2c9d Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Mon, 23 Feb 2026 07:35:03 -0600 Subject: [PATCH 07/31] Missing branch from CRTAnalysis --- sbndcode/CRT/CRTAna/CRTAnalysis_module.cc | 5 +++++ sbndcode/CRT/CRTAna/crtana_sbnd.fcl | 1 + 2 files changed, 6 insertions(+) diff --git a/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc b/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc index 29f6614c9..08b1f8202 100644 --- a/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc +++ b/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc @@ -323,6 +323,7 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { std::vector _tpc_end_dir_z; std::vector _tpc_length; std::vector _tpc_track_score; + std::vector _tpc_whichtpc; std::vector _tpc_truth_trackid; std::vector _tpc_truth_pdg; std::vector _tpc_truth_energy; @@ -621,6 +622,7 @@ sbnd::crt::CRTAnalysis::CRTAnalysis(fhicl::ParameterSet const& p) fTree->Branch("tpc_end_dir_z", "std::vector", &_tpc_end_dir_z); fTree->Branch("tpc_length", "std::vector", &_tpc_length); fTree->Branch("tpc_track_score", "std::vector", &_tpc_track_score); + fTree->Branch("tpc_whichtpc", "std::vector", &_tpc_whichtpc); fTree->Branch("tpc_sp_matched", "std::vector", &_tpc_sp_matched); fTree->Branch("tpc_sp_channel_set", "std::vector>", &_tpc_sp_channel_set); fTree->Branch("tpc_sp_xshift", "std::vector", &_tpc_sp_xshift); @@ -1682,6 +1684,7 @@ void sbnd::crt::CRTAnalysis::AnalyseTPCMatching(const art::Event &e, const art:: _tpc_end_dir_z.resize(nTracks); _tpc_length.resize(nTracks); _tpc_track_score.resize(nTracks); + _tpc_whichtpc.resize(nTracks); _tpc_truth_trackid.resize(nTracks); _tpc_truth_pdg.resize(nTracks); _tpc_truth_energy.resize(nTracks); @@ -1771,6 +1774,7 @@ void sbnd::crt::CRTAnalysis::AnalyseTPCMatching(const art::Event &e, const art:: const art::Ptr crttrack = tracksToTrackMatches.at(track.key()); const std::vector> trackHits = tracksToHits.at(track.key()); + _tpc_whichtpc[nActualTracks] = TPCGeoUtil::DetectedInTPC(trackHits); if(spacepoint.isNonnull()) { @@ -1915,6 +1919,7 @@ void sbnd::crt::CRTAnalysis::AnalyseTPCMatching(const art::Event &e, const art:: _tpc_end_dir_z.resize(nActualTracks); _tpc_length.resize(nActualTracks); _tpc_track_score.resize(nActualTracks); + _tpc_whichtpc.resize(nActualTracks); _tpc_truth_trackid.resize(nActualTracks); _tpc_truth_pdg.resize(nActualTracks); _tpc_truth_energy.resize(nActualTracks); diff --git a/sbndcode/CRT/CRTAna/crtana_sbnd.fcl b/sbndcode/CRT/CRTAna/crtana_sbnd.fcl index f0a36b111..1ab588870 100644 --- a/sbndcode/CRT/CRTAna/crtana_sbnd.fcl +++ b/sbndcode/CRT/CRTAna/crtana_sbnd.fcl @@ -17,6 +17,7 @@ crtana_sbnd: crtana_data_sbnd: @local::crtana_sbnd crtana_data_sbnd.FEBDataModuleLabel: "crtdecoder" crtana_data_sbnd.DataMode: true +crtana_data_sbnd.NoTPC: false crtana_data_sbnd.HasPTB: true crtana_data_sbnd.HasTDC: true From b67448063cc0a9c20449afecf4640dbe9a11c8b3 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Mon, 23 Feb 2026 07:53:20 -0600 Subject: [PATCH 08/31] Add ADRIFT - module for CRT calibration --- sbndcode/CRT/CRTAna/ADRIFT_module.cc | 1420 +++++++++++++++++++++++ sbndcode/CRT/CRTAna/CMakeLists.txt | 2 + sbndcode/CRT/CRTAna/adrift_sbnd.fcl | 31 + sbndcode/CRT/CRTAna/run_adrift_data.fcl | 28 + 4 files changed, 1481 insertions(+) create mode 100644 sbndcode/CRT/CRTAna/ADRIFT_module.cc create mode 100644 sbndcode/CRT/CRTAna/adrift_sbnd.fcl create mode 100644 sbndcode/CRT/CRTAna/run_adrift_data.fcl diff --git a/sbndcode/CRT/CRTAna/ADRIFT_module.cc b/sbndcode/CRT/CRTAna/ADRIFT_module.cc new file mode 100644 index 000000000..01727c94a --- /dev/null +++ b/sbndcode/CRT/CRTAna/ADRIFT_module.cc @@ -0,0 +1,1420 @@ +//////////////////////////////////////////////////////////////////////// +// Class: ADRIFT +// Plugin Type: analyzer +// File: ADRIFT_module.cc +// +// Author: Henry Lay (h.lay@sheffield.ac.uk) +// +// ADC +// Dynamic +// Range +// Improvement +// Facilitation +// Trees +//////////////////////////////////////////////////////////////////////// + +#include "art/Framework/Core/EDAnalyzer.h" +#include "art/Framework/Core/ModuleMacros.h" +#include "art/Framework/Principal/Event.h" +#include "art/Framework/Principal/Handle.h" +#include "art/Framework/Principal/Run.h" +#include "art/Framework/Principal/SubRun.h" +#include "canvas/Utilities/InputTag.h" +#include "fhiclcpp/ParameterSet.h" +#include "messagefacility/MessageLogger/MessageLogger.h" +#include "art_root_io/TFileService.h" +#include "canvas/Persistency/Common/FindManyP.h" +#include "canvas/Persistency/Common/FindOneP.h" + +#include "TTree.h" +#include "TH1D.h" +#include "TF1.h" +#include "TFitResultPtr.h" +#include "TFitResult.h" +#include "TCanvas.h" +#include "TSystem.h" +#include "TStyle.h" +#include "TText.h" + +#include "artdaq-core/Data/RawEvent.hh" + +#include "sbnobj/SBND/CRT/FEBData.hh" +#include "sbnobj/SBND/CRT/CRTStripHit.hh" +#include "sbnobj/SBND/CRT/CRTCluster.hh" +#include "sbnobj/SBND/CRT/CRTSpacePoint.hh" +#include "sbnobj/SBND/CRT/CRTTrack.hh" + +#include "sbndcode/Geometry/GeometryWrappers/CRTGeoService.h" +#include "sbndcode/ChannelMaps/CRT/CRTChannelMapService.h" + +namespace sbnd { + namespace crt { + class ADRIFT; + } +} + + +class sbnd::crt::ADRIFT : public art::EDAnalyzer { +public: + explicit ADRIFT(fhicl::ParameterSet const& p); + // The compiler-generated destructor is fine for non-base + // classes without bare pointers or other resource use. + + // Plugins should not be copied or assigned. + ADRIFT(ADRIFT const&) = delete; + ADRIFT(ADRIFT&&) = delete; + ADRIFT& operator=(ADRIFT const&) = delete; + ADRIFT& operator=(ADRIFT&&) = delete; + + // Required functions. + void analyze(art::Event const& e) override; + + // Selected optional functions. + void beginJob() override; + void endJob() override; + +private: + + void MakeSaveDirectories(art::Event const &e); + void AnalyseFEBDatas(art::Event const &e, const int window); + void AnalyseStripHits(art::Event const &e, const int window); + void AnalyseSpacePoints(art::Event const &e, const int window); + void AnalyseTracks(art::Event const &e, const int window); + void ProcessEntry(const int ch, const int window); + void PedestalFit(TH1D* hADC, double &fit, double &std, double &chi2, bool &converged, + bool badChannel, const int window); + void PedestalPeak(TH1D* hADC, double &peak); + void Rate(TH1D* hADC, double &rate, int window, double &period); + void PeakPeak(TH1D* hADC, const double &ped, double &peak); + void PeakFit(TH1D* hADC, const double &peak, const double &ped, double &fit, + double &chi2, bool &converged, bool badChannel, const int window); + double Saturation(TH1D* hADC); + void ResetVars(); + void SaveHist(TH1D *hADC, std::string &saveDir, std::string saveName, int rebin, bool badChannel); + static double LanGau(double *x, double *par); + + art::ServiceHandle fCRTGeoService; + + // Inputs + std::string fFEBDataModuleLabel, fCRTStripHitModuleLabel, fCRTClusterModuleLabel, + fCRTSpacePointModuleLabel, fCRTTrackModuleLabel, fDAQHeaderModuleLabel, fDAQHeaderInstanceLabel, + fTopSaveDirectory; + + bool fOnly2HitSpacePoints, fSaveAllFits, fSaveBadFits, fSaveSubset, fFEBs, fStripHits, fSpacePoints, + fTracks, fTrackLA, fSaveROOTHists, fAnalysePE; + + double fTrackAngleLimit, fPullWindow, fReconstructionWindow; + + uint32_t fRawTSCorrection; + + std::vector> fUnixWindows; + + // Other Global Parameters + std::vector fNEvents; + + TTree* fChannelTree; + + uint64_t _unix_start, _unix_end; + int _n_events, _channel, _gdml_id, _mac5, _raw_channel, _tagger, _channel_status; + double _area, _y_average, _ped_calib, _gain_calib, _ped_fit, _ped_fit_std, _ped_fit_chi2, _ped_peak, + _ped_reset_fit, _ped_reset_fit_std, _ped_reset_fit_chi2, _ped_reset_peak, _raw_max_chan_rate, _sh_rate, _sp_rate, _tr_rate, + _sh_peak_fit, _sh_peak_fit_chi2, _sh_peak_peak, _sh_pe_peak_fit, _sh_pe_peak_fit_chi2, _sh_pe_peak_peak, + _sh_sat_rate, _sh_sat_ratio_total, _sh_sat_ratio_peak, _sp_peak_fit, _sp_peak_fit_chi2, _sp_peak_peak, + _sp_pe_peak_fit, _sp_pe_peak_fit_chi2, _sp_pe_peak_peak, _sp_sat_rate, _sp_sat_ratio_total, _sp_sat_ratio_peak, + _tr_peak_fit, _tr_peak_fit_chi2, _tr_peak_peak, _tr_pe_peak_fit, _tr_pe_peak_fit_chi2, _tr_pe_peak_peak, + _tr_sat_rate, _tr_sat_ratio_total, _tr_sat_ratio_peak, _tr_lim_angle_peak_fit, _tr_lim_angle_peak_fit_chi2, _tr_lim_angle_peak_peak, + _tr_lim_angle_pe_peak_fit, _tr_lim_angle_pe_peak_fit_chi2, _tr_lim_angle_pe_peak_peak, _tr_lim_angle_sat_rate, + _tr_lim_angle_sat_ratio_total, _tr_lim_angle_sat_ratio_peak, _sh_ped_to_peak_fit, _sh_ped_reset_to_peak_fit, + _tr_by_length_peak_fit, _tr_by_length_peak_fit_chi2, _tr_by_length_peak_peak, + _tr_by_length_pe_peak_fit, _tr_by_length_pe_peak_fit_chi2, _tr_by_length_pe_peak_peak; + bool _horizontal, _ped_fit_converged, _ped_reset_fit_converged, _sh_peak_fit_converged, _sh_pe_peak_fit_converged, + _sp_peak_fit_converged, _sp_pe_peak_fit_converged, _tr_peak_fit_converged, _tr_pe_peak_fit_converged, _tr_lim_angle_peak_fit_converged, + _tr_lim_angle_pe_peak_fit_converged, _tr_by_length_peak_fit_converged, _tr_by_length_pe_peak_fit_converged; + + std::map> hADCPed, hADCPedReset, hADCMaxChan, hADCSH, hPESH, hADCSP, hPESP, hADCTr, hPETr, + hADCTrLA, hPETrLA, hADCTrByLength, hPETrByLength; + + std::map fPedestalSaveDirectory, fPedestalResetSaveDirectory, fPeakSaveDirectory, fBadPedestalSaveDirectory, + fBadPedestalResetSaveDirectory, fBadPeakSaveDirectory, fPedestalSubsetSaveDirectory, fPedestalResetSubsetSaveDirectory, + fStripHitSubsetSaveDirectory, fStripHitPESubsetSaveDirectory, fSpacePointSubsetSaveDirectory, fSpacePointPESubsetSaveDirectory, + fTrackSubsetSaveDirectory, fTrackPESubsetSaveDirectory, fTrackLASubsetSaveDirectory, fTrackLAPESubsetSaveDirectory, + fTrackByLengthSubsetSaveDirectory, fTrackByLengthPESubsetSaveDirectory; +}; + + +sbnd::crt::ADRIFT::ADRIFT(fhicl::ParameterSet const& p) + : EDAnalyzer{p} +{ + fFEBDataModuleLabel = p.get("FEBDataModuleLabel"); + fCRTStripHitModuleLabel = p.get("CRTStripHitModuleLabel"); + fCRTClusterModuleLabel = p.get("CRTClusterModuleLabel"); + fCRTSpacePointModuleLabel = p.get("CRTSpacePointModuleLabel"); + fCRTTrackModuleLabel = p.get("CRTTrackModuleLabel"); + fDAQHeaderModuleLabel = p.get("DAQHeaderModuleLabel"); + fDAQHeaderInstanceLabel = p.get("DAQHeaderInstanceLabel"); + fTopSaveDirectory = p.get("TopSaveDirectory"); + fOnly2HitSpacePoints = p.get("Only2HitSpacePoints"); + fSaveAllFits = p.get("SaveAllFits"); + fSaveBadFits = p.get("SaveBadFits"); + fSaveSubset = p.get("SaveSubset"); + fFEBs = p.get("FEBs"); + fStripHits = p.get("StripHits"); + fSpacePoints = p.get("SpacePoints"); + fTracks = p.get("Tracks"); + fTrackLA = p.get("TrackLA"); + fSaveROOTHists = p.get("SaveROOTHists"); + fAnalysePE = p.get("AnalysePE"); + fTrackAngleLimit = p.get("TrackAngleLimit"); + fPullWindow = p.get("PullWindow"); + fReconstructionWindow = p.get("ReconstructionWindow"); + fRawTSCorrection = p.get("RawTSCorrection"); + fUnixWindows = p.get>>("UnixWindows", { {0, std::numeric_limits::max()} }); + + art::ServiceHandle fs; + + fChannelTree = fs->make("channel_tree", ""); + fChannelTree->Branch("unix_start", &_unix_start); + fChannelTree->Branch("unix_end", &_unix_end); + fChannelTree->Branch("n_events", &_n_events); + fChannelTree->Branch("channel", &_channel); + fChannelTree->Branch("gdml_id", &_gdml_id); + fChannelTree->Branch("mac5", &_mac5); + fChannelTree->Branch("raw_channel", &_raw_channel); + fChannelTree->Branch("tagger", &_tagger); + fChannelTree->Branch("channel_status", &_channel_status); + fChannelTree->Branch("area", &_area); + fChannelTree->Branch("y_average", &_y_average); + fChannelTree->Branch("horizontal", &_horizontal); + fChannelTree->Branch("ped_calib", &_ped_calib); + fChannelTree->Branch("gain_calib", &_gain_calib); + if(fFEBs) + { + fChannelTree->Branch("ped_fit", &_ped_fit); + fChannelTree->Branch("ped_fit_std", &_ped_fit_std); + fChannelTree->Branch("ped_fit_chi2", &_ped_fit_chi2); + fChannelTree->Branch("ped_fit_converged", &_ped_fit_converged); + fChannelTree->Branch("ped_peak", &_ped_peak); + fChannelTree->Branch("ped_reset_fit", &_ped_reset_fit); + fChannelTree->Branch("ped_reset_fit_std", &_ped_reset_fit_std); + fChannelTree->Branch("ped_reset_fit_chi2", &_ped_reset_fit_chi2); + fChannelTree->Branch("ped_reset_fit_converged", &_ped_reset_fit_converged); + fChannelTree->Branch("ped_reset_peak", &_ped_reset_peak); + fChannelTree->Branch("raw_max_chan_rate", &_raw_max_chan_rate); + } + if(fStripHits) + { + fChannelTree->Branch("sh_rate", &_sh_rate); + fChannelTree->Branch("sh_peak_fit", &_sh_peak_fit); + fChannelTree->Branch("sh_peak_fit_chi2", &_sh_peak_fit_chi2); + fChannelTree->Branch("sh_peak_fit_converged", &_sh_peak_fit_converged); + fChannelTree->Branch("sh_peak_peak", &_sh_peak_peak); + fChannelTree->Branch("sh_sat_rate", &_sh_sat_rate); + fChannelTree->Branch("sh_sat_ratio_total", &_sh_sat_ratio_total); + fChannelTree->Branch("sh_sat_ratio_peak", &_sh_sat_ratio_peak); + fChannelTree->Branch("sh_ped_to_peak_fit", &_sh_ped_to_peak_fit); + fChannelTree->Branch("sh_ped_reset_to_peak_fit", &_sh_ped_reset_to_peak_fit); + + if(fAnalysePE) + { + fChannelTree->Branch("sh_pe_peak_fit", &_sh_pe_peak_fit); + fChannelTree->Branch("sh_pe_peak_fit_chi2", &_sh_pe_peak_fit_chi2); + fChannelTree->Branch("sh_pe_peak_fit_converged", &_sh_pe_peak_fit_converged); + fChannelTree->Branch("sh_pe_peak_peak", &_sh_pe_peak_peak); + } + } + if(fSpacePoints) + { + fChannelTree->Branch("sp_rate", &_sp_rate); + fChannelTree->Branch("sp_peak_fit", &_sp_peak_fit); + fChannelTree->Branch("sp_peak_fit_chi2", &_sp_peak_fit_chi2); + fChannelTree->Branch("sp_peak_fit_converged", &_sp_peak_fit_converged); + fChannelTree->Branch("sp_peak_peak", &_sp_peak_peak); + fChannelTree->Branch("sp_sat_rate", &_sp_sat_rate); + fChannelTree->Branch("sp_sat_ratio_total", &_sp_sat_ratio_total); + fChannelTree->Branch("sp_sat_ratio_peak", &_sp_sat_ratio_peak); + + if(fAnalysePE) + { + fChannelTree->Branch("sp_pe_peak_fit", &_sp_pe_peak_fit); + fChannelTree->Branch("sp_pe_peak_fit_chi2", &_sp_pe_peak_fit_chi2); + fChannelTree->Branch("sp_pe_peak_fit_converged", &_sp_pe_peak_fit_converged); + fChannelTree->Branch("sp_pe_peak_peak", &_sp_pe_peak_peak); + } + } + if(fTracks) + { + fChannelTree->Branch("tr_rate", &_tr_rate); + fChannelTree->Branch("tr_peak_fit", &_tr_peak_fit); + fChannelTree->Branch("tr_peak_fit_chi2", &_tr_peak_fit_chi2); + fChannelTree->Branch("tr_peak_fit_converged", &_tr_peak_fit_converged); + fChannelTree->Branch("tr_peak_peak", &_tr_peak_peak); + fChannelTree->Branch("tr_sat_rate", &_tr_sat_rate); + fChannelTree->Branch("tr_sat_ratio_total", &_tr_sat_ratio_total); + fChannelTree->Branch("tr_sat_ratio_peak", &_tr_sat_ratio_peak); + fChannelTree->Branch("tr_by_length_peak_fit", &_tr_by_length_peak_fit); + fChannelTree->Branch("tr_by_length_peak_fit_chi2", &_tr_by_length_peak_fit_chi2); + fChannelTree->Branch("tr_by_length_peak_fit_converged", &_tr_by_length_peak_fit_converged); + fChannelTree->Branch("tr_by_length_peak_peak", &_tr_by_length_peak_peak); + + if(fAnalysePE) + { + fChannelTree->Branch("tr_pe_peak_fit", &_tr_pe_peak_fit); + fChannelTree->Branch("tr_pe_peak_fit_chi2", &_tr_pe_peak_fit_chi2); + fChannelTree->Branch("tr_pe_peak_fit_converged", &_tr_pe_peak_fit_converged); + fChannelTree->Branch("tr_pe_peak_peak", &_tr_pe_peak_peak); + fChannelTree->Branch("tr_by_length_pe_peak_fit", &_tr_by_length_pe_peak_fit); + fChannelTree->Branch("tr_by_length_pe_peak_fit_chi2", &_tr_by_length_pe_peak_fit_chi2); + fChannelTree->Branch("tr_by_length_pe_peak_fit_converged", &_tr_by_length_pe_peak_fit_converged); + fChannelTree->Branch("tr_by_length_pe_peak_peak", &_tr_by_length_pe_peak_peak); + } + } + if(fTrackLA) + { + fChannelTree->Branch("tr_lim_angle_peak_fit", &_tr_lim_angle_peak_fit); + fChannelTree->Branch("tr_lim_angle_peak_fit_chi2", &_tr_lim_angle_peak_fit_chi2); + fChannelTree->Branch("tr_lim_angle_peak_fit_converged", &_tr_lim_angle_peak_fit_converged); + fChannelTree->Branch("tr_lim_angle_peak_peak", &_tr_lim_angle_peak_peak); + fChannelTree->Branch("tr_lim_angle_sat_rate", &_tr_lim_angle_sat_rate); + fChannelTree->Branch("tr_lim_angle_sat_ratio_total", &_tr_lim_angle_sat_ratio_total); + fChannelTree->Branch("tr_lim_angle_sat_ratio_peak", &_tr_lim_angle_sat_ratio_peak); + + if(fAnalysePE) + { + fChannelTree->Branch("tr_lim_angle_pe_peak_fit", &_tr_lim_angle_pe_peak_fit); + fChannelTree->Branch("tr_lim_angle_pe_peak_fit_chi2", &_tr_lim_angle_pe_peak_fit_chi2); + fChannelTree->Branch("tr_lim_angle_pe_peak_fit_converged", &_tr_lim_angle_pe_peak_fit_converged); + fChannelTree->Branch("tr_lim_angle_pe_peak_peak", &_tr_lim_angle_pe_peak_peak); + } + } + + for(uint window = 0; window < fUnixWindows.size(); ++window) + { + if(fSaveROOTHists) + { + for(int ch = 0; ch < 4480; ++ch) + { + if(fFEBs) + { + hADCPed[window][ch] = fs->make(Form("hADCPed_Window%i_Channel%i", window, ch), ";ADC;Readouts", 1000, -.5, 999.5); + hADCPedReset[window][ch] = fs->make(Form("hADCPedReset_Window%i_Channel%i", window, ch), ";ADC;Readouts", 1000, -.5, 999.5); + hADCMaxChan[window][ch] = fs->make(Form("hADCMaxChan_Window%i_Channel%i", window, ch), ";ADC;Readouts - Max Channel", 4300, -.5, 4299.5); + } + + if(fStripHits) + { + hADCSH[window][ch] = fs->make(Form("hADCSH_Window%i_Channel%i", window, ch), ";ADC;Strip Hits", 4300, -.5, 4299.5); + + if(fAnalysePE) + hPESH[window][ch] = fs->make(Form("hPESH_Window%i_Channel%i", window, ch), ";PE;Strip Hits", 4000, 0, 200); + } + + if(fSpacePoints) + { + hADCSP[window][ch] = fs->make(Form("hADCSP_Window%i_Channel%i", window, ch), ";ADC;Space Points", 4300, -.5, 4299.5); + + if(fAnalysePE) + hPESP[window][ch] = fs->make(Form("hPESP_Window%i_Channel%i", window, ch), ";PE;Space Points", 4000, 0, 200); + } + + if(fTracks) + { + hADCTr[window][ch] = fs->make(Form("hADCTr_Window%i_Channel%i", window, ch), ";ADC;Tracks", 4300, -.5, 4299.5); + hADCTrByLength[window][ch] = fs->make(Form("hADCTrByLength_Window%i_Channel%i", window, ch), ";ADC/Path Length;Tracks", 4300, -.5, 4299.5); + + if(fAnalysePE) + { + hPETr[window][ch] = fs->make(Form("hPETr_Window%i_Channel%i", window, ch), ";PE;Tracks", 4000, 0, 200); + hPETrByLength[window][ch] = fs->make(Form("hPETrByLength_Window%i_Channel%i", window, ch), ";PE/Path Length;Tracks", 4000, 0, 200); + } + } + + if(fTrackLA) + { + hADCTrLA[window][ch] = fs->make(Form("hADCTrLA_Window%i_Channel%i", window, ch), ";ADC;Tracks", 4300, -.5, 4299.5); + + if(fAnalysePE) + hPETrLA[window][ch] = fs->make(Form("hPETrLA_Window%i_Channel%i", window, ch), ";PE;Tracks", 4000, 0, 200); + } + } + } + else + { + for(int ch = 0; ch < 4480; ++ch) + { + if(fFEBs) + { + hADCPed[window][ch] = new TH1D(Form("hADCPed_Window%i_Channel%i", window, ch), ";ADC;Readouts", 1000, -.5, 999.5); + hADCPedReset[window][ch] = new TH1D(Form("hADCPedReset_Window%i_Channel%i", window, ch), ";ADC;Readouts", 1000, -.5, 999.5); + hADCMaxChan[window][ch] = new TH1D(Form("hADCMaxChan_Window%i_Channel%i", window, ch), ";ADC;Readouts - Max Channel", 4300, -.5, 4299.5); + } + + if(fStripHits) + { + hADCSH[window][ch] = new TH1D(Form("hADCSH_Window%i_Channel%i", window, ch), ";ADC;Strip Hits", 4300, -.5, 4299.5); + + if(fAnalysePE) + hPESH[window][ch] = new TH1D(Form("hPESH_Window%i_Channel%i", window, ch), ";PE;Strip Hits", 4000, 0, 200); + } + + if(fSpacePoints) + { + hADCSP[window][ch] = new TH1D(Form("hADCSP_Window%i_Channel%i", window, ch), ";ADC;Space Points", 4300, -.5, 4299.5); + + if(fAnalysePE) + hPESP[window][ch] = new TH1D(Form("hPESP_Window%i_Channel%i", window, ch), ";PE;Space Points", 4000, 0, 200); + } + + if(fTracks) + { + hADCTr[window][ch] = new TH1D(Form("hADCTr_Window%i_Channel%i", window, ch), ";ADC;Tracks", 4300, -.5, 4299.5); + hADCTrByLength[window][ch] = new TH1D(Form("hADCTrByLength_Window%i_Channel%i", window, ch), ";ADC/Path Length;Tracks", 4300, -.5, 4299.5); + + if(fAnalysePE) + { + hPETr[window][ch] = new TH1D(Form("hPETr_Window%i_Channel%i", window, ch), ";PE;Tracks", 4000, 0, 200); + hPETrByLength[window][ch] = new TH1D(Form("hPETrByLength_Window%i_Channel%i", window, ch), ";PE/Path Length;Tracks", 4000, 0, 200); + } + } + + if(fTrackLA) + { + hADCTrLA[window][ch] = new TH1D(Form("hADCTrLA_Window%i_Channel%i", window, ch), ";ADC;Tracks", 4300, -.5, 4299.5); + + if(fAnalysePE) + hPETrLA[window][ch] = new TH1D(Form("hPETrLA_Window%i_Channel%i", window, ch), ";PE;Tracks", 4000, 0, 200); + } + } + } + } + + for(uint i = 0; i < fUnixWindows.size(); ++i) + { + for(uint ii = i + 1; ii < fUnixWindows.size(); ++ii) + { + if(fUnixWindows[i].second > fUnixWindows[ii].first) + { + std::cout << "Unix windows overlap!" << std::endl; + throw std::exception(); + } + } + } +} + +void sbnd::crt::ADRIFT::analyze(art::Event const& e) +{ + // Get Raw TS + art::Handle DAQHeaderHandle; + e.getByLabel(fDAQHeaderModuleLabel, fDAQHeaderInstanceLabel, DAQHeaderHandle); + if(!DAQHeaderHandle.isValid()){ + std::cout << "RawEventHeader product " << fDAQHeaderModuleLabel << " - " << fDAQHeaderInstanceLabel << " not found..." << std::endl; + throw std::exception(); + } + artdaq::RawEvent rawHeaderEvent = artdaq::RawEvent(*DAQHeaderHandle); + uint64_t raw_ts = rawHeaderEvent.timestamp() - fRawTSCorrection; + + uint window = 0; + bool found = false; + + for(uint i = 0; i < fUnixWindows.size(); ++i) + { + if(raw_ts > fUnixWindows[i].first && raw_ts < fUnixWindows[i].second) + { + window = i; + found = true; + break; + } + } + + if(!found) + return; + + if(std::accumulate(fNEvents.begin(), fNEvents.end(), 0) == 0) + MakeSaveDirectories(e); + + if(fFEBs) + AnalyseFEBDatas(e, window); + + if(fStripHits) + AnalyseStripHits(e, window); + + if(fSpacePoints) + AnalyseSpacePoints(e, window); + + if(fTracks || fTrackLA) + AnalyseTracks(e, window); + + ++fNEvents[window]; +} + +void sbnd::crt::ADRIFT::MakeSaveDirectories(art::Event const &e) +{ + for(uint window = 0; window < fUnixWindows.size(); ++window) + { + std::string directory_structure = fUnixWindows.size() == 1 ? Form("run%i", e.run()) : Form("run%i/window%i", e.run(), window); + + if((fSaveAllFits || fSaveBadFits)) + { + gSystem->Exec(Form("mkdir -p %s", fTopSaveDirectory.c_str())); + + if(fFEBs) + { + fPedestalSaveDirectory[window] = Form("%s/%s/pedestals", fTopSaveDirectory.c_str(), directory_structure.c_str()); + gSystem->Exec(Form("mkdir -p %s", fPedestalSaveDirectory[window].c_str())); + + fPedestalResetSaveDirectory[window] = Form("%s/%s/pedestals_reset", fTopSaveDirectory.c_str(), directory_structure.c_str()); + gSystem->Exec(Form("mkdir -p %s", fPedestalResetSaveDirectory[window].c_str())); + + fBadPedestalSaveDirectory[window] = Form("%s/%s/pedestals/bad", fTopSaveDirectory.c_str(), directory_structure.c_str()); + gSystem->Exec(Form("mkdir -p %s", fBadPedestalSaveDirectory[window].c_str())); + + fBadPedestalResetSaveDirectory[window] = Form("%s/%s/pedestals_reset/bad", fTopSaveDirectory.c_str(), directory_structure.c_str()); + gSystem->Exec(Form("mkdir -p %s", fBadPedestalResetSaveDirectory[window].c_str())); + } + + if(fStripHits || fSpacePoints || fTracks || fTrackLA) + { + fPeakSaveDirectory[window] = Form("%s/%s/peaks", fTopSaveDirectory.c_str(), directory_structure.c_str()); + gSystem->Exec(Form("mkdir -p %s", fPeakSaveDirectory[window].c_str())); + + fBadPeakSaveDirectory[window] = Form("%s/%s/peaks/bad", fTopSaveDirectory.c_str(), directory_structure.c_str()); + gSystem->Exec(Form("mkdir -p %s", fBadPeakSaveDirectory[window].c_str())); + } + } + + if(fSaveSubset) + { + gSystem->Exec(Form("mkdir -p %s", fTopSaveDirectory.c_str())); + + if(fFEBs) + { + fPedestalSubsetSaveDirectory[window] = Form("%s/%s/subset/pedestals", fTopSaveDirectory.c_str(), directory_structure.c_str()); + gSystem->Exec(Form("mkdir -p %s", fPedestalSubsetSaveDirectory[window].c_str())); + + fPedestalResetSubsetSaveDirectory[window] = Form("%s/%s/subset/pedestals_reset", fTopSaveDirectory.c_str(), directory_structure.c_str()); + gSystem->Exec(Form("mkdir -p %s", fPedestalResetSubsetSaveDirectory[window].c_str())); + } + + if(fStripHits) + { + fStripHitSubsetSaveDirectory[window] = Form("%s/%s/subset/striphits", fTopSaveDirectory.c_str(), directory_structure.c_str()); + gSystem->Exec(Form("mkdir -p %s", fStripHitSubsetSaveDirectory[window].c_str())); + + if(fAnalysePE) + { + fStripHitPESubsetSaveDirectory[window] = Form("%s/%s/subset/striphits_pe", fTopSaveDirectory.c_str(), directory_structure.c_str()); + gSystem->Exec(Form("mkdir -p %s", fStripHitPESubsetSaveDirectory[window].c_str())); + } + } + + if(fSpacePoints) + { + fSpacePointSubsetSaveDirectory[window] = Form("%s/%s/subset/spacepoints", fTopSaveDirectory.c_str(), directory_structure.c_str()); + gSystem->Exec(Form("mkdir -p %s", fSpacePointSubsetSaveDirectory[window].c_str())); + + if(fAnalysePE) + { + fSpacePointPESubsetSaveDirectory[window] = Form("%s/%s/subset/spacepoints_pe", fTopSaveDirectory.c_str(), directory_structure.c_str()); + gSystem->Exec(Form("mkdir -p %s", fSpacePointPESubsetSaveDirectory[window].c_str())); + } + } + + if(fTracks) + { + fTrackSubsetSaveDirectory[window] = Form("%s/%s/subset/tracks", fTopSaveDirectory.c_str(), directory_structure.c_str()); + gSystem->Exec(Form("mkdir -p %s", fTrackSubsetSaveDirectory[window].c_str())); + + fTrackByLengthSubsetSaveDirectory[window] = Form("%s/%s/subset/tracks_by_length", fTopSaveDirectory.c_str(), directory_structure.c_str()); + gSystem->Exec(Form("mkdir -p %s", fTrackByLengthSubsetSaveDirectory[window].c_str())); + + if(fAnalysePE) + { + fTrackPESubsetSaveDirectory[window] = Form("%s/%s/subset/tracks_pe", fTopSaveDirectory.c_str(), directory_structure.c_str()); + gSystem->Exec(Form("mkdir -p %s", fTrackPESubsetSaveDirectory[window].c_str())); + + fTrackByLengthPESubsetSaveDirectory[window] = Form("%s/%s/subset/tracks_by_length_pe", fTopSaveDirectory.c_str(), directory_structure.c_str()); + gSystem->Exec(Form("mkdir -p %s", fTrackByLengthPESubsetSaveDirectory[window].c_str())); + } + } + + if(fTrackLA) + { + fTrackLASubsetSaveDirectory[window] = Form("%s/%s/subset/tracks_limited_angle", fTopSaveDirectory.c_str(), directory_structure.c_str()); + gSystem->Exec(Form("mkdir -p %s", fTrackLASubsetSaveDirectory[window].c_str())); + + if(fAnalysePE) + { + fTrackLAPESubsetSaveDirectory[window] = Form("%s/%s/subset/tracks_limited_angle_pe", fTopSaveDirectory.c_str(), directory_structure.c_str()); + gSystem->Exec(Form("mkdir -p %s", fTrackLAPESubsetSaveDirectory[window].c_str())); + } + } + } + } + + if((fSaveAllFits || fSaveBadFits || fSaveSubset)) + { + gStyle->SetOptStat(0); + gStyle->SetFrameLineWidth(2); + gStyle->SetTextFont(62); + gStyle->SetTextSize(0.07); + gStyle->SetLabelFont(62, "xyz"); + gStyle->SetLabelSize(0.05, "xyz"); + gStyle->SetTitleSize(0.05, "xyz"); + gStyle->SetTitleFont(62, "xyz"); + } +} + +void sbnd::crt::ADRIFT::AnalyseFEBDatas(art::Event const &e, const int window) +{ + // Get FEBDatas + art::Handle> FEBDataHandle; + e.getByLabel(fFEBDataModuleLabel, FEBDataHandle); + if(!FEBDataHandle.isValid()){ + std::cout << "FEBData product " << fFEBDataModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + std::vector> FEBDataVec; + art::fill_ptr_vector(FEBDataVec, FEBDataHandle); + + // Get FEBData to CRTStripHit Assns + art::FindManyP febDatasToStripHits(FEBDataHandle, e, fCRTStripHitModuleLabel); + + for(const art::Ptr &feb_data : FEBDataVec) + { + const std::vector> strip_hits = febDatasToStripHits.at(feb_data.key()); + const uint m5 = feb_data->Mac5(); + const uint flags = feb_data->Flags(); + + std::set mask_channels; + + for(const art::Ptr &strip_hit : strip_hits) + { + mask_channels.insert(strip_hit->Channel()); + mask_channels.insert(strip_hit->Channel() + 1); + + if(strip_hit->Channel() % 2) + std::cout << "ODD Strip Hit Channel Number" << std::endl; + } + + int max_adc = -1, max_chan = -1; + + for(int i = 0; i < 32; ++i) + { + if(feb_data->ADC(i) > max_adc) + { + max_adc = feb_data->ADC(i); + max_chan = i; + } + + const int ch = m5 * 32 + i; + + if(!mask_channels.count(ch)) + hADCPed[window][ch]->Fill(feb_data->ADC(i)); + + if(flags != 1 && flags != 3) + hADCPedReset[window][ch]->Fill(feb_data->ADC(i)); + } + + if((flags == 1 || flags == 3) && max_chan != -1) + hADCMaxChan[window][m5 * 32 + max_chan]->Fill(feb_data->ADC(max_chan)); + } +} + +void sbnd::crt::ADRIFT::AnalyseStripHits(art::Event const &e, const int window) +{ + // Get CRTStripHits + art::Handle> CRTStripHitHandle; + e.getByLabel(fCRTStripHitModuleLabel, CRTStripHitHandle); + if(!CRTStripHitHandle.isValid()){ + std::cout << "CRTStripHit product " << fCRTStripHitModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + std::vector> CRTStripHitVec; + art::fill_ptr_vector(CRTStripHitVec, CRTStripHitHandle); + + for(const art::Ptr &strip_hit : CRTStripHitVec) + { + if(strip_hit->Channel() % 2) + std::cout << "ODD Strip Hit Channel Number" << std::endl; + + CRTSiPMGeo sipm1 = fCRTGeoService->GetSiPM(strip_hit->Channel()); + CRTSiPMGeo sipm2 = fCRTGeoService->GetSiPM(strip_hit->Channel() + 1); + + hADCSH[window][strip_hit->Channel()]->Fill(strip_hit->ADC1() + sipm1.pedestal); + hADCSH[window][strip_hit->Channel() + 1]->Fill(strip_hit->ADC2() + sipm2.pedestal); + + if(fAnalysePE) + { + if((strip_hit->ADC1() + sipm1.pedestal) < 4089) + hPESH[window][strip_hit->Channel()]->Fill(strip_hit->ADC1() * sipm1.gain); + if((strip_hit->ADC2() + sipm2.pedestal) < 4089) + hPESH[window][strip_hit->Channel() + 1]->Fill(strip_hit->ADC2() * sipm2.gain); + } + } +} + +void sbnd::crt::ADRIFT::AnalyseSpacePoints(art::Event const &e, const int window) +{ + // Get CRTSpacePoints + art::Handle> CRTSpacePointHandle; + e.getByLabel(fCRTSpacePointModuleLabel, CRTSpacePointHandle); + if(!CRTSpacePointHandle.isValid()){ + std::cout << "CRTSpacePoint product " << fCRTSpacePointModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + std::vector> CRTSpacePointVec; + art::fill_ptr_vector(CRTSpacePointVec, CRTSpacePointHandle); + + // Get CRTClusters + art::Handle> CRTClusterHandle; + e.getByLabel(fCRTClusterModuleLabel, CRTClusterHandle); + if(!CRTClusterHandle.isValid()){ + std::cout << "CRTCluster product " << fCRTClusterModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + + // Get CRTSpacePoint to CRTCluster Assns + art::FindOneP spacepointsToClusters(CRTSpacePointHandle, e, fCRTSpacePointModuleLabel); + + // Get CRTCluster to CRTStripHit Assns + art::FindManyP clustersToStripHits(CRTClusterHandle, e, fCRTClusterModuleLabel); + + for(const art::Ptr &space_point : CRTSpacePointVec) + { + const art::Ptr cluster = spacepointsToClusters.at(space_point.key()); + + if(fOnly2HitSpacePoints && cluster->NHits() > 2) + continue; + + const std::vector> strip_hits = clustersToStripHits.at(cluster.key()); + + for(const art::Ptr &strip_hit : strip_hits) + { + if(strip_hit->Channel() % 2) + std::cout << "ODD Strip Hit Channel Number" << std::endl; + + CRTSiPMGeo sipm1 = fCRTGeoService->GetSiPM(strip_hit->Channel()); + CRTSiPMGeo sipm2 = fCRTGeoService->GetSiPM(strip_hit->Channel() + 1); + + hADCSP[window][strip_hit->Channel()]->Fill(strip_hit->ADC1() + sipm1.pedestal); + hADCSP[window][strip_hit->Channel() + 1]->Fill(strip_hit->ADC2() + sipm2.pedestal); + + if(fAnalysePE) + { + if((strip_hit->ADC1() + sipm1.pedestal) < 4089) + hPESP[window][strip_hit->Channel()]->Fill(strip_hit->ADC1() * sipm1.gain); + if((strip_hit->ADC2() + sipm2.pedestal) < 4089) + hPESP[window][strip_hit->Channel() + 1]->Fill(strip_hit->ADC2() * sipm2.gain); + } + } + } +} + +void sbnd::crt::ADRIFT::AnalyseTracks(art::Event const &e, const int window) +{ + // Get CRTTracks + art::Handle> CRTTrackHandle; + e.getByLabel(fCRTTrackModuleLabel, CRTTrackHandle); + if(!CRTTrackHandle.isValid()){ + std::cout << "CRTTrack product " << fCRTTrackModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + std::vector> CRTTrackVec; + art::fill_ptr_vector(CRTTrackVec, CRTTrackHandle); + + // Get CRTSpacePoints + art::Handle> CRTSpacePointHandle; + e.getByLabel(fCRTSpacePointModuleLabel, CRTSpacePointHandle); + if(!CRTSpacePointHandle.isValid()){ + std::cout << "CRTSpacePoint product " << fCRTSpacePointModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + + // Get CRTClusters + art::Handle> CRTClusterHandle; + e.getByLabel(fCRTClusterModuleLabel, CRTClusterHandle); + if(!CRTClusterHandle.isValid()){ + std::cout << "CRTCluster product " << fCRTClusterModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + + // Get CRTTrack to CRTSpacePoint Assns + art::FindManyP tracksToSpacePoints(CRTTrackHandle, e, fCRTTrackModuleLabel); + + // Get CRTSpacePoint to CRTCluster Assns + art::FindOneP spacepointsToClusters(CRTSpacePointHandle, e, fCRTSpacePointModuleLabel); + + // Get CRTCluster to CRTStripHit Assns + art::FindManyP clustersToStripHits(CRTClusterHandle, e, fCRTClusterModuleLabel); + + for(const art::Ptr &track : CRTTrackVec) + { + const std::vector> space_points = tracksToSpacePoints.at(track.key()); + + const geo::Vector_t tr_dir_vec = track->Direction(); + const TVector3 tr_dir = TVector3(tr_dir_vec.X(), tr_dir_vec.Y(), tr_dir_vec.Z()); + + for(const art::Ptr &space_point : space_points) + { + const art::Ptr cluster = spacepointsToClusters.at(space_point.key()); + + const std::vector> strip_hits = clustersToStripHits.at(cluster.key()); + const CRTTagger tagger = cluster->Tagger(); + TVector3 normal; + if(tagger == kBottomTagger || tagger == kTopLowTagger || tagger == kTopHighTagger) + normal = TVector3(0, 1, 0); + else if(tagger == kWestTagger || tagger == kEastTagger) + normal = TVector3(1, 0, 0); + else if(tagger == kSouthTagger || tagger == kNorthTagger) + normal = TVector3(0, 0, 1); + + const double angle = TMath::RadToDeg() * normal.Angle(tr_dir); + const double path_length = 1 / TMath::Cos(normal.Angle(tr_dir)); + + for(const art::Ptr &strip_hit : strip_hits) + { + if(strip_hit->Channel() % 2) + std::cout << "ODD Strip Hit Channel Number" << std::endl; + + CRTSiPMGeo sipm1 = fCRTGeoService->GetSiPM(strip_hit->Channel()); + CRTSiPMGeo sipm2 = fCRTGeoService->GetSiPM(strip_hit->Channel() + 1); + + if(fTracks) + { + hADCTr[window][strip_hit->Channel()]->Fill(strip_hit->ADC1() + sipm1.pedestal); + hADCTr[window][strip_hit->Channel() + 1]->Fill(strip_hit->ADC2() + sipm2.pedestal); + + if(fAnalysePE) + { + if((strip_hit->ADC1() + sipm1.pedestal) < 4089) + hPETr[window][strip_hit->Channel()]->Fill(strip_hit->ADC1() * sipm1.gain); + if((strip_hit->ADC2() + sipm2.pedestal) < 4089) + hPETr[window][strip_hit->Channel() + 1]->Fill(strip_hit->ADC2() * sipm2.gain); + } + + if((strip_hit->ADC1() + sipm1.pedestal) < 4089) + { + hADCTrByLength[window][strip_hit->Channel()]->Fill((strip_hit->ADC1() + sipm1.pedestal) / path_length); + + if(fAnalysePE && (strip_hit->ADC1() + sipm1.pedestal) < 4089) + hPETrByLength[window][strip_hit->Channel()]->Fill((strip_hit->ADC1() * sipm1.gain) / path_length); + } + if((strip_hit->ADC2() + sipm2.pedestal) < 4089) + { + hADCTrByLength[window][strip_hit->Channel() + 1]->Fill((strip_hit->ADC2() + sipm2.pedestal) / path_length); + + if(fAnalysePE && (strip_hit->ADC2() + sipm2.pedestal) < 4089) + hPETrByLength[window][strip_hit->Channel() + 1]->Fill((strip_hit->ADC2() * sipm2.gain) / path_length); + } + } + + if(fTrackLA && angle < fTrackAngleLimit) + { + hADCTrLA[window][strip_hit->Channel()]->Fill(strip_hit->ADC1() + sipm1.pedestal); + hADCTrLA[window][strip_hit->Channel() + 1]->Fill(strip_hit->ADC2() + sipm2.pedestal); + + if(fAnalysePE) + { + if((strip_hit->ADC1() + sipm1.pedestal) < 4089) + hPETrLA[window][strip_hit->Channel()]->Fill(strip_hit->ADC1() * sipm1.gain); + if((strip_hit->ADC2() + sipm2.pedestal) < 4089) + hPETrLA[window][strip_hit->Channel() + 1]->Fill(strip_hit->ADC2() * sipm2.gain); + } + } + } + } + } +} + +void sbnd::crt::ADRIFT::beginJob() +{ + fNEvents = std::vector(fUnixWindows.size(), 0); +} + +void sbnd::crt::ADRIFT::endJob() +{ + art::ServiceHandle ChannelMapService; + + for(int gdml_i = 0; gdml_i < 140; ++gdml_i) + { + ResetVars(); + + std::cout << "=== Processing module " << gdml_i << std::endl; + + uint mac5 = ChannelMapService->GetMAC5FromOfflineModuleID(gdml_i); + bool invert = ChannelMapService->GetInversionFromOfflineModuleID(gdml_i); + + for(int ch_i = 0; ch_i < 32; ++ch_i) + { + const int ch = ChannelMapService->ConstructOfflineChannelIDFromOfflineModuleIDAndOfflineLocalChannel(gdml_i, ch_i); + + _channel = ch; + _gdml_id = gdml_i; + _mac5 = mac5; + _raw_channel = invert ? 31 - ch_i : ch_i; + _tagger = fCRTGeoService->ChannelToTaggerEnum(ch); + _channel_status = fCRTGeoService->GetSiPM(ch).status; + _area = fCRTGeoService->StripArea(ch); + _y_average = fCRTGeoService->StripAverageY(ch); + _ped_calib = fCRTGeoService->GetSiPM(ch).pedestal; + _gain_calib = fCRTGeoService->GetSiPM(ch).gain; + _horizontal = _tagger == kBottomTagger || _tagger == kTopLowTagger || _tagger == kTopHighTagger; + + for(uint window = 0; window < fUnixWindows.size(); ++window) + ProcessEntry(ch, window); + } + } +} + +void sbnd::crt::ADRIFT::ProcessEntry(const int ch, const int window) +{ + _unix_start = fUnixWindows[window].first; + _unix_end = fUnixWindows[window].second; + _n_events = fNEvents[window]; + + if(fSaveSubset && (ch > 1471 && ch < 1728)) + { + if(fFEBs) + { + SaveHist(hADCPed[window][ch], fPedestalSubsetSaveDirectory[window], Form("pedestal_channel_%i", ch), 2, _channel_status); + SaveHist(hADCPedReset[window][ch], fPedestalResetSubsetSaveDirectory[window], Form("pedestal_reset_channel_%i", ch), 2, _channel_status); + } + + if(fStripHits) + { + SaveHist(hADCSH[window][ch], fStripHitSubsetSaveDirectory[window], Form("strip_hit_channel_%i", ch), 20, _channel_status); + + if(fAnalysePE) + SaveHist(hPESH[window][ch], fStripHitPESubsetSaveDirectory[window], Form("strip_hit_pe_channel_%i", ch), 20, _channel_status); + } + + if(fSpacePoints) + { + SaveHist(hADCSP[window][ch], fSpacePointSubsetSaveDirectory[window], Form("space_point_channel_%i", ch), 20, _channel_status); + if(fAnalysePE) + SaveHist(hPESP[window][ch], fSpacePointPESubsetSaveDirectory[window], Form("space_point_pe_channel_%i", ch), 20, _channel_status); + } + + if(fTracks) + { + SaveHist(hADCTr[window][ch], fTrackSubsetSaveDirectory[window], Form("track_channel_%i", ch), 20, _channel_status); + SaveHist(hADCTrByLength[window][ch], fTrackByLengthSubsetSaveDirectory[window], Form("track_by_length_channel_%i", ch), 20, _channel_status); + if(fAnalysePE) + { + SaveHist(hPETr[window][ch], fTrackPESubsetSaveDirectory[window], Form("track_pe_channel_%i", ch), 20, _channel_status); + SaveHist(hPETrByLength[window][ch], fTrackByLengthPESubsetSaveDirectory[window], Form("track_by_length_pe_channel_%i", ch), 20, _channel_status); + } + } + + if(fTrackLA) + { + SaveHist(hADCTrLA[window][ch], fTrackLASubsetSaveDirectory[window], Form("track_limited_angle_channel_%i", ch), 20, _channel_status); + if(fAnalysePE) + SaveHist(hPETrLA[window][ch], fTrackLAPESubsetSaveDirectory[window], Form("track_limited_angle_pe_channel_%i", ch), 20, _channel_status); + } + + } + + if(fFEBs) + { + PedestalFit(hADCPed[window][ch], _ped_fit, _ped_fit_std, _ped_fit_chi2, _ped_fit_converged, _channel_status, window); + PedestalPeak(hADCPed[window][ch], _ped_peak); + + PedestalFit(hADCPedReset[window][ch], _ped_reset_fit, _ped_reset_fit_std, _ped_reset_fit_chi2, _ped_reset_fit_converged, _channel_status, window); + PedestalPeak(hADCPedReset[window][ch], _ped_reset_peak); + + Rate(hADCMaxChan[window][ch], _raw_max_chan_rate, window, fPullWindow); + } + + if(fStripHits) + { + Rate(hADCSH[window][ch], _sh_rate, window, fReconstructionWindow); + + PeakPeak(hADCSH[window][ch], _ped_calib, _sh_peak_peak); + PeakFit(hADCSH[window][ch], _sh_peak_peak, _ped_calib, _sh_peak_fit, _sh_peak_fit_chi2, _sh_peak_fit_converged, _channel_status, window); + _sh_ped_to_peak_fit = _sh_peak_fit - _ped_fit; + _sh_ped_reset_to_peak_fit = _sh_peak_fit - _ped_reset_fit; + + if(fAnalysePE) + { + PeakPeak(hPESH[window][ch], _ped_calib, _sh_pe_peak_peak); + PeakFit(hPESH[window][ch], _sh_pe_peak_peak, _ped_calib, _sh_pe_peak_fit, _sh_pe_peak_fit_chi2, _sh_pe_peak_fit_converged, _channel_status, window); + } + + const double sh_sat = Saturation(hADCSH[window][ch]); + _sh_sat_rate = sh_sat / (fNEvents[window] * fReconstructionWindow); + _sh_sat_ratio_total = sh_sat / hADCSH[window][ch]->GetEntries(); + _sh_sat_ratio_peak = sh_sat / hADCSH[window][ch]->GetBinContent(hADCSH[window][ch]->FindBin(_sh_peak_peak)); + } + + if(fSpacePoints) + { + Rate(hADCSP[window][ch], _sp_rate, window, fReconstructionWindow); + + PeakPeak(hADCSP[window][ch], _ped_calib, _sp_peak_peak); + PeakFit(hADCSP[window][ch], _sp_peak_peak, _ped_calib, _sp_peak_fit, _sp_peak_fit_chi2, _sp_peak_fit_converged, _channel_status, window); + + if(fAnalysePE) + { + PeakPeak(hPESP[window][ch], _ped_calib, _sp_pe_peak_peak); + PeakFit(hPESP[window][ch], _sp_pe_peak_peak, _ped_calib, _sp_pe_peak_fit, _sp_pe_peak_fit_chi2, _sp_pe_peak_fit_converged, _channel_status, window); + } + + const double sp_sat = Saturation(hADCSP[window][ch]); + _sp_sat_rate = sp_sat / (fNEvents[window] * fReconstructionWindow); + _sp_sat_ratio_total = sp_sat / hADCSP[window][ch]->GetEntries(); + _sp_sat_ratio_peak = sp_sat / hADCSP[window][ch]->GetBinContent(hADCSP[window][ch]->FindBin(_sp_peak_peak)); + } + + if(fTracks && _tagger != kBottomTagger) + { + Rate(hADCTr[window][ch], _tr_rate, window, fReconstructionWindow); + + PeakPeak(hADCTr[window][ch], _ped_calib, _tr_peak_peak); + PeakFit(hADCTr[window][ch], _tr_peak_peak, _ped_calib, _tr_peak_fit, _tr_peak_fit_chi2, _tr_peak_fit_converged, _channel_status, window); + + PeakPeak(hADCTrByLength[window][ch], _ped_calib, _tr_by_length_peak_peak); + PeakFit(hADCTrByLength[window][ch], _tr_by_length_peak_peak, _ped_calib, _tr_by_length_peak_fit, _tr_by_length_peak_fit_chi2, _tr_by_length_peak_fit_converged, _channel_status, window); + + if(fAnalysePE) + { + PeakPeak(hPETr[window][ch], _ped_calib, _tr_pe_peak_peak); + PeakFit(hPETr[window][ch], _tr_pe_peak_peak, _ped_calib, _tr_pe_peak_fit, _tr_pe_peak_fit_chi2, _tr_pe_peak_fit_converged, _channel_status, window); + + PeakPeak(hPETrByLength[window][ch], _ped_calib, _tr_by_length_pe_peak_peak); + PeakFit(hPETrByLength[window][ch], _tr_by_length_pe_peak_peak, _ped_calib, _tr_by_length_pe_peak_fit, _tr_by_length_pe_peak_fit_chi2, _tr_by_length_pe_peak_fit_converged, _channel_status, window); + } + + const double tr_sat = Saturation(hADCTr[window][ch]); + _tr_sat_rate = tr_sat / (fNEvents[window] * fReconstructionWindow); + _tr_sat_ratio_total = tr_sat / hADCTr[window][ch]->GetEntries(); + _tr_sat_ratio_peak = tr_sat / hADCTr[window][ch]->GetBinContent(hADCTr[window][ch]->FindBin(_tr_peak_peak)); + } + + if(fTrackLA && _tagger != kBottomTagger) + { + PeakPeak(hADCTrLA[window][ch], _ped_calib, _tr_lim_angle_peak_peak); + PeakFit(hADCTrLA[window][ch], _tr_lim_angle_peak_peak, _ped_calib, _tr_lim_angle_peak_fit, _tr_lim_angle_peak_fit_chi2, _tr_lim_angle_peak_fit_converged, _channel_status, window); + + if(fAnalysePE) + { + PeakPeak(hPETrLA[window][ch], _ped_calib, _tr_lim_angle_pe_peak_peak); + PeakFit(hPETrLA[window][ch], _tr_lim_angle_pe_peak_peak, _ped_calib, _tr_lim_angle_pe_peak_fit, _tr_lim_angle_pe_peak_fit_chi2, _tr_lim_angle_pe_peak_fit_converged, _channel_status, window); + } + + const double tr_lim_angle_sat = Saturation(hADCTrLA[window][ch]); + _tr_lim_angle_sat_rate = tr_lim_angle_sat / (fNEvents[window] * fReconstructionWindow); + _tr_lim_angle_sat_ratio_total = tr_lim_angle_sat / hADCTrLA[window][ch]->GetEntries(); + _tr_lim_angle_sat_ratio_peak = tr_lim_angle_sat / hADCTrLA[window][ch]->GetBinContent(hADCTrLA[window][ch]->FindBin(_tr_lim_angle_peak_peak)); + } + + fChannelTree->Fill(); +} + +void sbnd::crt::ADRIFT::PedestalFit(TH1D* hADC, double &fit, double &std, double &chi2, bool &converged, + bool badChannel, const int window) +{ + TF1 *gaus = new TF1("gaus", "gaus", 0, 500); + const TString name = hADC->GetName(); + TString ch_name = name; + TString type = ""; + + const int window_log = window == 0 ? 0 : std::floor(std::log10(window)); + + if(name.Contains("Reset")) + { + ch_name.Remove(0, 27 + window_log + 1); + type = "reset"; + } + else + ch_name.Remove(0,22 + window_log + 1); + + int ch = std::stoi(ch_name.Data()); + + TH1D* hADC2 = (TH1D*) hADC->Clone(name + "_for_fit"); + hADC2->Rebin(5); + + TFitResultPtr fit_result = hADC2->Fit(gaus, "QRS"); + converged = !(bool)(int(fit_result)); + + if(!converged && !badChannel) + std::cout << "Pedestal fit has not converged - " << hADC->GetName() << std::endl; + + fit = gaus->GetParameter("Mean"); + std = gaus->GetParameter("Sigma"); + chi2 = gaus->GetChisquare() / gaus->GetNDF(); + + if(fSaveAllFits || (fSaveBadFits && !converged) || (fSaveSubset && ch > 1471 && ch < 1728)) + { + TCanvas *c = new TCanvas(Form("c%s", name.Data()), Form("c%s", name.Data())); + c->cd(); + + hADC2->SetLineColor(kOrange+2); + hADC2->SetLineWidth(2); + hADC2->Draw("histe"); + gaus->SetLineColor(kSpring-6); + gaus->Draw("same"); + + if(badChannel) + { + TText *t = new TText(.5, .75, "Bad Channel"); + t->SetTextSize(0.1); + t->SetTextColor(kRed); + t->Draw(); + } + + if(converged) + { + if(type.Contains("reset")) + { + c->SaveAs(Form("%s/pedestal_reset_fit_channel_%s.png", fPedestalResetSaveDirectory[window].c_str(), ch_name.Data())); + c->SaveAs(Form("%s/pedestal_reset_fit_channel_%s.pdf", fPedestalResetSaveDirectory[window].c_str(), ch_name.Data())); + } + else + { + c->SaveAs(Form("%s/pedestal_fit_channel_%s.png", fPedestalSaveDirectory[window].c_str(), ch_name.Data())); + c->SaveAs(Form("%s/pedestal_fit_channel_%s.pdf", fPedestalSaveDirectory[window].c_str(), ch_name.Data())); + } + } + else + { + if(type.Contains("reset")) + { + c->SaveAs(Form("%s/pedestal_reset_fit_channel_%s.png", fBadPedestalResetSaveDirectory[window].c_str(), ch_name.Data())); + c->SaveAs(Form("%s/pedestal_reset_fit_channel_%s.pdf", fBadPedestalResetSaveDirectory[window].c_str(), ch_name.Data())); + } + else + { + c->SaveAs(Form("%s/pedestal_fit_channel_%s.png", fBadPedestalSaveDirectory[window].c_str(), ch_name.Data())); + c->SaveAs(Form("%s/pedestal_fit_channel_%s.pdf", fBadPedestalSaveDirectory[window].c_str(), ch_name.Data())); + } + } + } +} + +void sbnd::crt::ADRIFT::PedestalPeak(TH1D* hADC, double &peak) +{ + const int bin = hADC->GetMaximumBin(); + + peak = hADC->GetBinCenter(bin); +} + +void sbnd::crt::ADRIFT::Rate(TH1D* hADC, double &rate, int window, double &period) +{ + rate = hADC->GetEntries() / (fNEvents[window] * period); +} + +void sbnd::crt::ADRIFT::PeakPeak(TH1D* hist, const double &ped, double &peak) +{ + int bin = 0; + double max = std::numeric_limits::lowest(); + + const TString name = hist->GetName(); + + const int start = name.Contains("PE") ? 0 : (int)ped + 20; + + for(int i = start; i < 4000; ++i) + { + if(hist->GetBinContent(i) > max) + { + max = hist->GetBinContent(i); + bin = i; + } + } + + peak = hist->GetBinCenter(bin); +} + +void sbnd::crt::ADRIFT::PeakFit(TH1D* hist, const double &peak, const double &ped, double &fit, + double &chi2, bool &converged, bool badChannel, const int window) +{ + const TString name = hist->GetName(); + const bool pe = name.Contains("PE"); + TString ch_name = name; + TString type = ""; + + const double start = pe ? 0 : ped + 20; + const double end = pe ? 200 : 4000; + const double width = pe ? 0.25 : 10; + const double sigma = pe ? 1 : 50; + + TF1 *langau = new TF1("langau", LanGau, start, end, 4); + double params[4] = { width, peak, hist->GetEntries(), sigma }; + langau->SetParameters(params); + + const int window_log = window == 0 ? 0 : std::floor(std::log10(window)); + + if(name.Contains("SH")) + { + const int end = pe ? 20 + window_log + 1 : 21 + window_log + 1; + ch_name.Remove(0, end); + type = "strip_hit"; + } + else if(name.Contains("SP")) + { + const int end = pe ? 20 + window_log + 1 : 21 + window_log + 1; + ch_name.Remove(0, end); + type = "space_point"; + } + else if(name.Contains("TrLA")) + { + const int end = pe ? 22 + window_log + 1 : 23 + window_log + 1; + ch_name.Remove(0, end); + type = "track_limited_angle"; + } + else if(name.Contains("TrByLength")) + { + const int end = pe ? 28 + window_log + 1 : 29 + window_log + 1; + ch_name.Remove(0, end); + type = "track_by_length"; + } + else if(name.Contains("Tr")) + { + const int end = pe ? 20 + window_log + 1 : 21 + window_log + 1; + ch_name.Remove(0, end); + type = "track"; + } + else + std::cout << "Cannot identify histogram type (" << name << ")" << std::endl; + + int ch = std::stoi(ch_name.Data()); + + TH1D* hist2 = (TH1D*) hist->Clone(name + "_for_fit"); + hist2->Rebin(20); + + TFitResultPtr fit_result = hist2->Fit(langau, "QRS"); + converged = !(bool)(int(fit_result)); + + if(!converged && !badChannel) + std::cout << "Peak fit has not converged - " << hist->GetName() << std::endl; + + fit = langau->GetParameter(1); + chi2 = langau->GetChisquare() / langau->GetNDF(); + + if(fSaveAllFits || (fSaveBadFits && !converged) || (fSaveSubset && ch > 1471 && ch < 1728)) + { + TCanvas *c = new TCanvas(Form("c%s", name.Data()), Form("c%s", name.Data())); + c->cd(); + + hist2->SetLineColor(kOrange+2); + hist2->SetLineWidth(2); + hist2->Draw("histe"); + langau->SetLineColor(kSpring-6); + langau->Draw("same"); + + if(badChannel) + { + TText *t = new TText(.5, .75, "Bad Channel"); + t->SetTextSize(0.1); + t->SetTextColor(kRed); + t->Draw(); + } + + if(pe) + { + if(converged) + { + c->SaveAs(Form("%s/peak_fit_%s_pe_channel_%s.png", fPeakSaveDirectory[window].c_str(), type.Data(), ch_name.Data())); + c->SaveAs(Form("%s/peak_fit_%s_pe_channel_%s.pdf", fPeakSaveDirectory[window].c_str(), type.Data(), ch_name.Data())); + } + else + { + c->SaveAs(Form("%s/peak_fit_%s_pe_channel_%s.png", fBadPeakSaveDirectory[window].c_str(), type.Data(), ch_name.Data())); + c->SaveAs(Form("%s/peak_fit_%s_pe_channel_%s.pdf", fBadPeakSaveDirectory[window].c_str(), type.Data(), ch_name.Data())); + } + } + else + { + if(converged) + { + c->SaveAs(Form("%s/peak_fit_%s_channel_%s.png", fPeakSaveDirectory[window].c_str(), type.Data(), ch_name.Data())); + c->SaveAs(Form("%s/peak_fit_%s_channel_%s.pdf", fPeakSaveDirectory[window].c_str(), type.Data(), ch_name.Data())); + } + else + { + c->SaveAs(Form("%s/peak_fit_%s_channel_%s.png", fBadPeakSaveDirectory[window].c_str(), type.Data(), ch_name.Data())); + c->SaveAs(Form("%s/peak_fit_%s_channel_%s.pdf", fBadPeakSaveDirectory[window].c_str(), type.Data(), ch_name.Data())); + } + } + } +} + +double sbnd::crt::ADRIFT::Saturation(TH1D* hADC) +{ + const double sat = hADC->GetBinContent(4090); + + for(int i = 4080; i < 4101; ++i) + { + if(i == 4090) + continue; + + if(hADC->GetBinContent(i) > sat) + std::cout << "Saturation appears to be in bin " << i << " (" << hADC->GetBinContent(i) + << ") not bin 4090 (" << sat << ")" << std::endl; + } + + return sat; +} + +void sbnd::crt::ADRIFT::ResetVars() +{ + _channel = std::numeric_limits::lowest(); + _gdml_id = std::numeric_limits::lowest(); + _mac5 = std::numeric_limits::lowest(); + _raw_channel = std::numeric_limits::lowest(); + _tagger = std::numeric_limits::lowest(); + _channel_status = std::numeric_limits::lowest(); + + _area = std::numeric_limits::lowest(); + _y_average = std::numeric_limits::lowest(); + _ped_calib = std::numeric_limits::lowest(); + _gain_calib = std::numeric_limits::lowest(); + _ped_fit = std::numeric_limits::lowest(); + _ped_fit_std = std::numeric_limits::lowest(); + _ped_fit_chi2 = std::numeric_limits::lowest(); + _ped_peak = std::numeric_limits::lowest(); + _ped_reset_fit = std::numeric_limits::lowest(); + _ped_reset_fit_std = std::numeric_limits::lowest(); + _ped_reset_fit_chi2 = std::numeric_limits::lowest(); + _ped_reset_peak = std::numeric_limits::lowest(); + _sh_rate = std::numeric_limits::lowest(); + _sp_rate = std::numeric_limits::lowest(); + _tr_rate = std::numeric_limits::lowest(); + _sh_peak_fit = std::numeric_limits::lowest(); + _sh_peak_fit_chi2 = std::numeric_limits::lowest(); + _sh_peak_peak = std::numeric_limits::lowest(); + _sh_sat_rate = std::numeric_limits::lowest(); + _sh_sat_ratio_total = std::numeric_limits::lowest(); + _sh_sat_ratio_peak = std::numeric_limits::lowest(); + _sh_ped_to_peak_fit = std::numeric_limits::lowest(); + _sh_ped_reset_to_peak_fit = std::numeric_limits::lowest(); + _sp_peak_fit = std::numeric_limits::lowest(); + _sp_peak_fit_chi2 = std::numeric_limits::lowest(); + _sp_peak_peak = std::numeric_limits::lowest(); + _sp_sat_rate = std::numeric_limits::lowest(); + _sp_sat_ratio_total = std::numeric_limits::lowest(); + _sp_sat_ratio_peak = std::numeric_limits::lowest(); + _tr_peak_fit = std::numeric_limits::lowest(); + _tr_peak_fit_chi2 = std::numeric_limits::lowest(); + _tr_peak_peak = std::numeric_limits::lowest(); + _tr_sat_rate = std::numeric_limits::lowest(); + _tr_sat_ratio_total = std::numeric_limits::lowest(); + _tr_sat_ratio_peak = std::numeric_limits::lowest(); + _tr_by_length_peak_fit = std::numeric_limits::lowest(); + _tr_by_length_peak_fit_chi2 = std::numeric_limits::lowest(); + _tr_by_length_peak_peak = std::numeric_limits::lowest(); + _tr_lim_angle_peak_fit = std::numeric_limits::lowest(); + _tr_lim_angle_peak_fit_chi2 = std::numeric_limits::lowest(); + _tr_lim_angle_peak_peak = std::numeric_limits::lowest(); + _tr_lim_angle_sat_rate = std::numeric_limits::lowest(); + _tr_lim_angle_sat_ratio_total = std::numeric_limits::lowest(); + _tr_lim_angle_sat_ratio_peak = std::numeric_limits::lowest(); + _sh_pe_peak_fit = std::numeric_limits::lowest(); + _sh_pe_peak_fit_chi2 = std::numeric_limits::lowest(); + _sh_pe_peak_peak = std::numeric_limits::lowest(); + _sp_pe_peak_fit = std::numeric_limits::lowest(); + _sp_pe_peak_fit_chi2 = std::numeric_limits::lowest(); + _sp_pe_peak_peak = std::numeric_limits::lowest(); + _tr_pe_peak_fit = std::numeric_limits::lowest(); + _tr_pe_peak_fit_chi2 = std::numeric_limits::lowest(); + _tr_pe_peak_peak = std::numeric_limits::lowest(); + _tr_by_length_pe_peak_fit = std::numeric_limits::lowest(); + _tr_by_length_pe_peak_fit_chi2 = std::numeric_limits::lowest(); + _tr_by_length_pe_peak_peak = std::numeric_limits::lowest(); + _tr_lim_angle_pe_peak_fit = std::numeric_limits::lowest(); + _tr_lim_angle_pe_peak_fit_chi2 = std::numeric_limits::lowest(); + _tr_lim_angle_pe_peak_peak = std::numeric_limits::lowest(); + + _horizontal = false; + _ped_fit_converged = false; + _ped_reset_fit_converged = false; + _sh_peak_fit_converged = false; + _sp_peak_fit_converged = false; + _tr_peak_fit_converged = false; + _tr_by_length_peak_fit_converged = false; + _tr_lim_angle_peak_fit_converged = false; + _sh_pe_peak_fit_converged = false; + _sp_pe_peak_fit_converged = false; + _tr_pe_peak_fit_converged = false; + _tr_by_length_pe_peak_fit_converged = false; + _tr_lim_angle_pe_peak_fit_converged = false; +} + +void sbnd::crt::ADRIFT::SaveHist(TH1D *hist, std::string &saveDir, std::string saveName, int rebin, bool badChannel) +{ + TCanvas *c = new TCanvas(Form("c%s", saveName.c_str()), Form("c%s", saveName.c_str())); + c->cd(); + + const TString name = hist->GetName(); + TH1D* hist2 = (TH1D*) hist->Clone(name + "_for_save"); + + hist2->SetLineColor(kOrange+2); + hist2->SetLineWidth(2); + hist2->Rebin(rebin); + hist2->Draw("histe"); + + if(badChannel) + { + TText *t = new TText(.5, .75, "Bad Channel"); + t->SetTextSize(0.1); + t->SetTextColor(kRed); + t->Draw(); + } + + c->SaveAs(Form("%s/%s.png", saveDir.c_str(), saveName.c_str())); + c->SaveAs(Form("%s/%s.pdf", saveDir.c_str(), saveName.c_str())); +} + +double sbnd::crt::ADRIFT::LanGau(double *x, double *par) +{ + //Fit parameters: + //par[0]=Width (scale) parameter of Landau density + //par[1]=Most Probable (MP, location) parameter of Landau density + //par[2]=Total area (integral -inf to inf, normalization constant) + //par[3]=Width (sigma) of convoluted Gaussian function + // + //In the Landau distribution (represented by the CERNLIB approximation), + //the maximum is located at x=-0.22278298 with the location parameter=0. + //This shift is corrected within this function, so that the actual + //maximum is identical to the MP parameter. + + // Numeric constants + double invsq2pi = 0.3989422804014; // (2 pi)^(-1/2) + double mpshift = -0.22278298; // Landau maximum location + + // Control constants + double np = 100.0; // number of convolution steps + double sc = 5.0; // convolution extends to +-sc Gaussian sigmas + + // Variables + double xx; + double mpc; + double fland; + double sum = 0.0; + double xlow,xupp; + double step; + double i; + + // MP shift correction + mpc = par[1] - mpshift * par[0]; + + // Range of convolution integral + xlow = x[0] - sc * par[3]; + xupp = x[0] + sc * par[3]; + + step = (xupp-xlow) / np; + + // Convolution integral of Landau and Gaussian by sum + for(i=1.0; i<=np/2; i++) { + xx = xlow + (i-.5) * step; + fland = TMath::Landau(xx,mpc,par[0]) / par[0]; + sum += fland * TMath::Gaus(x[0],xx,par[3]); + + xx = xupp - (i-.5) * step; + fland = TMath::Landau(xx,mpc,par[0]) / par[0]; + sum += fland * TMath::Gaus(x[0],xx,par[3]); + } + + return (par[2] * step * sum * invsq2pi / par[3]); +} + +DEFINE_ART_MODULE(sbnd::crt::ADRIFT) diff --git a/sbndcode/CRT/CRTAna/CMakeLists.txt b/sbndcode/CRT/CRTAna/CMakeLists.txt index 76a0241af..2cbcc6327 100644 --- a/sbndcode/CRT/CRTAna/CMakeLists.txt +++ b/sbndcode/CRT/CRTAna/CMakeLists.txt @@ -1,9 +1,11 @@ art_make( MODULE_LIBRARIES ROOT::Tree + ROOT::Graf3d art_root_io::TFileService_service larsim::Utils lardata::DetectorClocksService + sbndaq_artdaq_core::sbndaq-artdaq-core_Obj_SBND sbnobj::SBND_CRT sbnobj::SBND_Timing sbndcode_CRT_CRTBackTracker diff --git a/sbndcode/CRT/CRTAna/adrift_sbnd.fcl b/sbndcode/CRT/CRTAna/adrift_sbnd.fcl new file mode 100644 index 000000000..0be839450 --- /dev/null +++ b/sbndcode/CRT/CRTAna/adrift_sbnd.fcl @@ -0,0 +1,31 @@ +BEGIN_PROLOG + +adrift_data_sbnd: +{ + module_type: "ADRIFT" + FEBDataModuleLabel: "crtdecoder" + CRTStripHitModuleLabel: "crtstrips" + CRTClusterModuleLabel: "crtclustering" + CRTSpacePointModuleLabel: "crtspacepoints" + CRTTrackModuleLabel: "crttracks" + DAQHeaderModuleLabel: "daq" + DAQHeaderInstanceLabel: "RawEventHeader" + TopSaveDirectory: "/exp/sbnd/data/users/hlay/crt_comm_summer_2024/plots/adrift" + Only2HitSpacePoints: false + SaveAllFits: false + SaveBadFits: false + SaveSubset: false + FEBs: true + StripHits: true + SpacePoints: true + Tracks: true + TrackLA: true + SaveROOTHists: true + AnalysePE: false + TrackAngleLimit: 20 + PullWindow: 0.05 + ReconstructionWindow: 3.22e-3 + RawTSCorrection: 367000 +} + +END_PROLOG diff --git a/sbndcode/CRT/CRTAna/run_adrift_data.fcl b/sbndcode/CRT/CRTAna/run_adrift_data.fcl new file mode 100644 index 000000000..237978055 --- /dev/null +++ b/sbndcode/CRT/CRTAna/run_adrift_data.fcl @@ -0,0 +1,28 @@ +#include "services_sbnd.fcl" +#include "crt_services_sbnd.fcl" +#include "adrift_sbnd.fcl" + +process_name: ADRIFT + +services: +{ + TFileService: { fileName: "adrift_sbnd.root" } + @table::sbnd_basic_services + @table::crt_services_data_sbnd +} + +source: +{ + module_type: RootInput +} + +physics: +{ + analyzers: + { + adrift: @local::adrift_data_sbnd + } + + ana: [ adrift ] + end_paths: [ ana ] +} From 70411b58bddbd04c2d5a2f15a52b6f0f3ecc0129 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Mon, 23 Feb 2026 07:58:38 -0600 Subject: [PATCH 09/31] Add CRTRateAnalysis - module for CRT real time rate analysis --- sbndcode/CRT/CRTAna/CRTRateAnalysis_module.cc | 292 ++++++++++++++++++ sbndcode/CRT/CRTAna/crtrateana_sbnd.fcl | 13 + sbndcode/CRT/CRTAna/run_crtrateana_data.fcl | 28 ++ 3 files changed, 333 insertions(+) create mode 100644 sbndcode/CRT/CRTAna/CRTRateAnalysis_module.cc create mode 100644 sbndcode/CRT/CRTAna/crtrateana_sbnd.fcl create mode 100644 sbndcode/CRT/CRTAna/run_crtrateana_data.fcl diff --git a/sbndcode/CRT/CRTAna/CRTRateAnalysis_module.cc b/sbndcode/CRT/CRTAna/CRTRateAnalysis_module.cc new file mode 100644 index 000000000..418c9c250 --- /dev/null +++ b/sbndcode/CRT/CRTAna/CRTRateAnalysis_module.cc @@ -0,0 +1,292 @@ +//////////////////////////////////////////////////////////////////////// +// Class: CRTRateAnalysis +// Plugin Type: analyzer (Unknown Unknown) +// File: CRTRateAnalysis_module.cc +// +// Generated at Tue Jan 7 05:28:06 2025 by Henry Lay using cetskelgen +// from cetlib version 3.18.02. +//////////////////////////////////////////////////////////////////////// + +#include "art/Framework/Core/EDAnalyzer.h" +#include "art/Framework/Core/ModuleMacros.h" +#include "art/Framework/Principal/Event.h" +#include "art/Framework/Principal/Handle.h" +#include "art/Framework/Principal/Run.h" +#include "art/Framework/Principal/SubRun.h" +#include "canvas/Utilities/InputTag.h" +#include "fhiclcpp/ParameterSet.h" +#include "messagefacility/MessageLogger/MessageLogger.h" +#include "art_root_io/TFileService.h" + +#include "TTree.h" + +#include "canvas/Persistency/Common/FindOneP.h" +#include "canvas/Persistency/Common/FindManyP.h" + +#include "artdaq-core/Data/RawEvent.hh" + +#include "sbnobj/SBND/CRT/FEBData.hh" +#include "sbnobj/SBND/CRT/CRTSpacePoint.hh" +#include "sbnobj/SBND/CRT/CRTCluster.hh" +#include "sbnobj/SBND/CRT/CRTBlob.hh" + +#include "sbndcode/Geometry/GeometryWrappers/CRTGeoService.h" +#include "sbndcode/ChannelMaps/CRT/CRTChannelMapService.h" + +namespace sbnd { + namespace crt { + class CRTRateAnalysis; + } +} + + +class sbnd::crt::CRTRateAnalysis : public art::EDAnalyzer { +public: + explicit CRTRateAnalysis(fhicl::ParameterSet const& p); + // The compiler-generated destructor is fine for non-base + // classes without bare pointers or other resource use. + + // Plugins should not be copied or assigned. + CRTRateAnalysis(CRTRateAnalysis const&) = delete; + CRTRateAnalysis(CRTRateAnalysis&&) = delete; + CRTRateAnalysis& operator=(CRTRateAnalysis const&) = delete; + CRTRateAnalysis& operator=(CRTRateAnalysis&&) = delete; + + // Required functions. + void analyze(art::Event const& e) override; + + void ResetEventVars(); + void ResetRawVars(); + void ResetSpacePointVars(); + void ResetBlobVars(); + +private: + + art::ServiceHandle fCRTGeoService; + art::ServiceHandle fCRTChannelMapService; + + std::string fFEBDataModuleLabel, fCRTSpacePointModuleLabel, + fCRTBlobModuleLabel, fDAQHeaderModuleLabel, fDAQHeaderInstanceLabel; + + TTree *fEventTree, *fRawTree, *fSpacePointTree, *fBlobTree; + + int32_t _run, _subrun, _event; + uint32_t _event_header_ts; + + int16_t _tagger, _module; + uint16_t _max_channel; + + int16_t _n_hits; + double _x, _y, _z, _pe; + + int16_t _n_total_sps, _n_bottom_sps, _n_bottom_sps_twohits, _n_south_sps, + _n_north_sps, _n_west_sps, _n_east_sps, _n_toplow_sps, _n_tophigh_sps; +}; + + +sbnd::crt::CRTRateAnalysis::CRTRateAnalysis(fhicl::ParameterSet const& p) + : EDAnalyzer{p} + , fFEBDataModuleLabel(p.get("FEBDataModuleLabel")) + , fCRTSpacePointModuleLabel(p.get("CRTSpacePointModuleLabel")) + , fCRTBlobModuleLabel(p.get("CRTBlobModuleLabel")) + , fDAQHeaderModuleLabel(p.get("DAQHeaderModuleLabel")) + , fDAQHeaderInstanceLabel(p.get("DAQHeaderInstanceLabel")) +{ + art::ServiceHandle fs; + + fEventTree = fs->make("events", ""); + fEventTree->Branch("run", &_run); + fEventTree->Branch("subrun", &_subrun); + fEventTree->Branch("event", &_event); + fEventTree->Branch("event_header_ts", &_event_header_ts); + + fRawTree = fs->make("readouts", ""); + fRawTree->Branch("run", &_run); + fRawTree->Branch("subrun", &_subrun); + fRawTree->Branch("event", &_event); + fRawTree->Branch("event_header_ts", &_event_header_ts); + fRawTree->Branch("tagger", &_tagger); + fRawTree->Branch("module", &_module); + fRawTree->Branch("max_channel", &_max_channel); + + fSpacePointTree = fs->make("spacepoints", ""); + fSpacePointTree->Branch("run", &_run); + fSpacePointTree->Branch("subrun", &_subrun); + fSpacePointTree->Branch("event", &_event); + fSpacePointTree->Branch("event_header_ts", &_event_header_ts); + fSpacePointTree->Branch("tagger", &_tagger); + fSpacePointTree->Branch("n_hits", &_n_hits); + fSpacePointTree->Branch("x", &_x); + fSpacePointTree->Branch("y", &_y); + fSpacePointTree->Branch("z", &_z); + fSpacePointTree->Branch("pe", &_pe); + + fBlobTree = fs->make("blobs", ""); + fBlobTree->Branch("run", &_run); + fBlobTree->Branch("subrun", &_subrun); + fBlobTree->Branch("event", &_event); + fBlobTree->Branch("event_header_ts", &_event_header_ts); + fBlobTree->Branch("n_total_sps", &_n_total_sps); + fBlobTree->Branch("n_bottom_sps", &_n_bottom_sps); + fBlobTree->Branch("n_bottom_sps_twohits", &_n_bottom_sps_twohits); + fBlobTree->Branch("n_south_sps", &_n_south_sps); + fBlobTree->Branch("n_north_sps", &_n_north_sps); + fBlobTree->Branch("n_west_sps", &_n_west_sps); + fBlobTree->Branch("n_east_sps", &_n_east_sps); + fBlobTree->Branch("n_toplow_sps", &_n_toplow_sps); + fBlobTree->Branch("n_tophigh_sps", &_n_tophigh_sps); + fBlobTree->Branch("pe", &_pe); +} + +void sbnd::crt::CRTRateAnalysis::analyze(art::Event const& e) +{ + ResetEventVars(); + + _run = e.id().run(); + _subrun = e.id().subRun(); + _event = e.id().event(); + + art::Handle DAQHeaderHandle; + e.getByLabel(fDAQHeaderModuleLabel, fDAQHeaderInstanceLabel, DAQHeaderHandle); + + if(DAQHeaderHandle.isValid()) + { + artdaq::RawEvent rawHeaderEvent = artdaq::RawEvent(*DAQHeaderHandle); + uint64_t raw_ts = rawHeaderEvent.timestamp(); + _event_header_ts = raw_ts / static_cast(1e9); + } + + fEventTree->Fill(); + + art::Handle> FEBDataHandle; + e.getByLabel(fFEBDataModuleLabel, FEBDataHandle); + + std::vector> FEBDataVec; + art::fill_ptr_vector(FEBDataVec, FEBDataHandle); + + for(auto const& data : FEBDataVec) + { + ResetRawVars(); + _tagger = fCRTGeoService->AuxDetIndexToTaggerEnum(data->Mac5()); + _module = data->Mac5(); + + int max_adc = -1, max_ch = -1; + + for(int ch = 0; ch < 32; ++ch) + { + int adc = data->ADC(ch); + + if(adc > max_adc) + { + max_adc = adc; + max_ch = ch; + } + } + + _max_channel = fCRTChannelMapService->ConstructOfflineChannelIDFromOfflineModuleIDAndOfflineLocalChannel(_module, max_ch); + + fRawTree->Fill(); + } + + art::Handle> CRTSpacePointHandle; + e.getByLabel(fCRTSpacePointModuleLabel, CRTSpacePointHandle); + + std::vector> CRTSpacePointVec; + art::fill_ptr_vector(CRTSpacePointVec, CRTSpacePointHandle); + + art::FindOneP spacePointsToClusters(CRTSpacePointHandle, e, fCRTSpacePointModuleLabel); + + for(auto const& spacePoint : CRTSpacePointVec) + { + ResetSpacePointVars(); + + const art::Ptr cluster = spacePointsToClusters.at(spacePoint.key()); + + _tagger = cluster->Tagger(); + _n_hits = cluster->NHits(); + _x = spacePoint->X(); + _y = spacePoint->Y(); + _z = spacePoint->Z(); + _pe = spacePoint->PE(); + + fSpacePointTree->Fill(); + } + + art::Handle> CRTBlobHandle; + e.getByLabel(fCRTBlobModuleLabel, CRTBlobHandle); + + std::vector> CRTBlobVec; + art::fill_ptr_vector(CRTBlobVec, CRTBlobHandle); + + art::FindManyP blobsToSpacePoints(CRTBlobHandle, e, fCRTBlobModuleLabel); + + for(auto const& blob : CRTBlobVec) + { + ResetBlobVars(); + + _n_total_sps = blob->TotalSpacePoints(); + _n_bottom_sps = blob->SpacePointsInTagger(kBottomTagger); + _n_south_sps = blob->SpacePointsInTagger(kSouthTagger); + _n_north_sps = blob->SpacePointsInTagger(kNorthTagger); + _n_west_sps = blob->SpacePointsInTagger(kWestTagger); + _n_east_sps = blob->SpacePointsInTagger(kEastTagger); + _n_toplow_sps = blob->SpacePointsInTagger(kTopLowTagger); + _n_tophigh_sps = blob->SpacePointsInTagger(kTopHighTagger); + _pe = blob->PE(); + + _n_bottom_sps_twohits = 0; + + const std::vector> spacePoints = blobsToSpacePoints.at(blob.key()); + + for(auto const& spacePoint : spacePoints) + { + const art::Ptr cluster = spacePointsToClusters.at(spacePoint.key()); + + if(cluster->Tagger() == kBottomTagger && cluster->NHits() > 1) + ++_n_bottom_sps_twohits; + } + + fBlobTree->Fill(); + } +} + +void sbnd::crt::CRTRateAnalysis::ResetEventVars() +{ + _run = -1; _subrun = -1; _event = -1; + _event_header_ts = std::numeric_limits::max(); +} + +void sbnd::crt::CRTRateAnalysis::ResetRawVars() +{ + _tagger = -1; _module = -1; + _max_channel = std::numeric_limits::max(); +} + +void sbnd::crt::CRTRateAnalysis::ResetSpacePointVars() +{ + _tagger = -1; + + _n_hits = -1; + + _x = std::numeric_limits::lowest(); + _y = std::numeric_limits::lowest(); + _z = std::numeric_limits::lowest(); + _pe = std::numeric_limits::lowest(); +} + +void sbnd::crt::CRTRateAnalysis::ResetBlobVars() +{ + _n_total_sps = -1; + _n_bottom_sps = -1; + _n_bottom_sps_twohits = -1; + _n_south_sps = -1; + _n_north_sps = -1; + _n_west_sps = -1; + _n_east_sps = -1; + _n_toplow_sps = -1; + _n_tophigh_sps = -1; + + _pe = std::numeric_limits::lowest(); +} + +DEFINE_ART_MODULE(sbnd::crt::CRTRateAnalysis) diff --git a/sbndcode/CRT/CRTAna/crtrateana_sbnd.fcl b/sbndcode/CRT/CRTAna/crtrateana_sbnd.fcl new file mode 100644 index 000000000..b9ffc2186 --- /dev/null +++ b/sbndcode/CRT/CRTAna/crtrateana_sbnd.fcl @@ -0,0 +1,13 @@ +BEGIN_PROLOG + +crtrateana_data_sbnd: +{ + FEBDataModuleLabel: "crtdecoder" + CRTSpacePointModuleLabel: "crtspacepoints" + CRTBlobModuleLabel: "crtblobs" + DAQHeaderModuleLabel: "daq" + DAQHeaderInstanceLabel: "RawEventHeader" + module_type: "CRTRateAnalysis" +} + +END_PROLOG diff --git a/sbndcode/CRT/CRTAna/run_crtrateana_data.fcl b/sbndcode/CRT/CRTAna/run_crtrateana_data.fcl new file mode 100644 index 000000000..b3c6f1c4e --- /dev/null +++ b/sbndcode/CRT/CRTAna/run_crtrateana_data.fcl @@ -0,0 +1,28 @@ +#include "services_sbnd.fcl" +#include "crt_services_sbnd.fcl" +#include "crtrateana_sbnd.fcl" + +process_name: CRTRateAnalysis + +services: +{ + @table::sbnd_basic_services + @table::crt_services_data_sbnd + TFileService: { fileName: "crtrateana_sbnd.root" } +} + +source: +{ + module_type: RootInput +} + +physics: +{ + analyzers: + { + crtrateana: @local::crtrateana_data_sbnd + } + + ana: [ crtrateana ] + end_paths: [ ana ] +} From a446e0ba31d7b8d4c6d2a0a444d83bee8ef55a74 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Mon, 23 Feb 2026 08:10:50 -0600 Subject: [PATCH 10/31] Add CRTTopHatAnalysis - module for CRT beam top hat analysis --- .../CRT/CRTAna/CRTTopHatAnalysis_module.cc | 821 ++++++++++++++++++ sbndcode/CRT/CRTAna/crttophatana_sbnd.fcl | 12 + sbndcode/CRT/CRTAna/run_crttophatana_data.fcl | 28 + 3 files changed, 861 insertions(+) create mode 100644 sbndcode/CRT/CRTAna/CRTTopHatAnalysis_module.cc create mode 100644 sbndcode/CRT/CRTAna/crttophatana_sbnd.fcl create mode 100644 sbndcode/CRT/CRTAna/run_crttophatana_data.fcl diff --git a/sbndcode/CRT/CRTAna/CRTTopHatAnalysis_module.cc b/sbndcode/CRT/CRTAna/CRTTopHatAnalysis_module.cc new file mode 100644 index 000000000..f338ce846 --- /dev/null +++ b/sbndcode/CRT/CRTAna/CRTTopHatAnalysis_module.cc @@ -0,0 +1,821 @@ +//////////////////////////////////////////////////////////////////////// +// Class: CRTTopHatAnalysis +// Plugin Type: analyzer +// File: CRTTopHatAnalysis_module.cc +// Author: Henry Lay (h.lay@sheffield.ac.uk) +//////////////////////////////////////////////////////////////////////// + +#include "art/Framework/Core/EDAnalyzer.h" +#include "art/Framework/Core/ModuleMacros.h" +#include "art/Framework/Principal/Event.h" +#include "art/Framework/Principal/Handle.h" +#include "art/Framework/Principal/Run.h" +#include "art/Framework/Principal/SubRun.h" +#include "canvas/Utilities/InputTag.h" +#include "fhiclcpp/ParameterSet.h" +#include "messagefacility/MessageLogger/MessageLogger.h" +#include "art_root_io/TFileService.h" +#include "canvas/Persistency/Common/FindManyP.h" + +#include "TTree.h" + +#include "lardataobj/AnalysisBase/T0.h" +#include "lardataobj/RecoBase/Track.h" +#include "lardataobj/RecoBase/PFParticle.h" +#include "lardataobj/RecoBase/PFParticleMetadata.h" + +#include "larsim/Utils/TruthMatchUtils.h" +#include "lardata/DetectorInfoServices/DetectorClocksService.h" + +#include "sbndaq-artdaq-core/Obj/SBND/pmtSoftwareTrigger.hh" + +#include "sbnobj/SBND/CRT/FEBData.hh" +#include "sbnobj/SBND/CRT/CRTStripHit.hh" +#include "sbnobj/SBND/CRT/CRTCluster.hh" +#include "sbnobj/SBND/CRT/CRTSpacePoint.hh" +#include "sbnobj/SBND/CRT/CRTTrack.hh" +#include "sbnobj/SBND/Timing/DAQTimestamp.hh" + +#include "sbndcode/Geometry/GeometryWrappers/CRTGeoService.h" +#include "sbndcode/Geometry/GeometryWrappers/TPCGeoAlg.h" +#include "sbndcode/CRT/CRTBackTracker/CRTBackTrackerAlg.h" +#include "sbndcode/CRT/CRTUtils/CRTCommonUtils.h" +#include "sbndcode/Decoders/PTB/sbndptb.h" +#include "sbndcode/Timing/SBNDRawTimingObj.h" + +namespace sbnd::crt { + class CRTTopHatAnalysis; +} + +class sbnd::crt::CRTTopHatAnalysis : public art::EDAnalyzer { +public: + explicit CRTTopHatAnalysis(fhicl::ParameterSet const& p); + // The compiler-generated destructor is fine for non-base + // classes without bare pointers or other resource use. + + // Plugins should not be copied or assigned. + CRTTopHatAnalysis(CRTTopHatAnalysis const&) = delete; + CRTTopHatAnalysis(CRTTopHatAnalysis&&) = delete; + CRTTopHatAnalysis& operator=(CRTTopHatAnalysis const&) = delete; + CRTTopHatAnalysis& operator=(CRTTopHatAnalysis&&) = delete; + + // Required functions. + void analyze(art::Event const& e) override; + + void AnalysePTBs(std::vector> &PTBVec); + + void AnalyseTDCs(std::vector> &TDCVec); + + void SortReferencing(); + + void AnalyseCRTStripHits(const art::Event &e, const std::vector> &CRTStripHitVec); + + void AnalyseCRTClusters(const art::Event &e, const std::vector> &CRTClusterVec, + const art::FindManyP &clustersToSpacePoints); + + void AnalyseCRTTracks(const art::Event &e, const std::vector> &CRTTrackVec); + + void AnalysePMTSoftwareTriggers(const art::Event &e, const std::vector> &PMTSoftwareTriggerVec); + + +private: + + art::ServiceHandle fCRTGeoService; + TPCGeoAlg fTPCGeoAlg; + + std::string fCRTStripHitModuleLabel, fCRTClusterModuleLabel, fCRTSpacePointModuleLabel, + fCRTTrackModuleLabel, fPTBModuleLabel, fTDCModuleLabel, fTimingReferenceModuleLabel, + fPMTSoftwareTriggerModuleLabel; + bool fDebug, fCutT0, fSavePMTSoftwareTrigger; + double fMinT0, fMaxT0; + std::vector fAllowedPTBHLTs; + + TTree* fTree; + + // Tree variables + + int _run; + int _subrun; + int _event; + int _crt_timing_reference_type; + int _crt_timing_reference_channel; + + //strip hit to select the strip which has ADC above threshold + std::vector _sh_channel; + std::vector _sh_tagger; + std::vector _sh_ts0; + std::vector _sh_ts0_rwm_ref; + std::vector _sh_ts0_ptb_hlt_beam_gate_ref; + std::vector _sh_ts1; + std::vector _sh_ts1_rwm_ref; + std::vector _sh_ts1_ptb_hlt_beam_gate_ref; + std::vector _sh_unixs; + std::vector _sh_pos; + std::vector _sh_err; + std::vector _sh_adc1; + std::vector _sh_adc2; + std::vector _sh_saturated1; + std::vector _sh_saturated2; + std::vector _sh_truth_trackid; + std::vector _sh_truth_completeness; + std::vector _sh_truth_purity; + std::vector _sh_truth_pos; + std::vector _sh_truth_energy; + std::vector _sh_truth_time; + + //cluster from x-y coincidence for CRTSpacePoint + std::vector _cl_ts0; + std::vector _cl_ts0_rwm_ref; + std::vector _cl_ts0_ptb_hlt_beam_gate_ref; + std::vector _cl_ts1; + std::vector _cl_ts1_rwm_ref; + std::vector _cl_ts1_ptb_hlt_beam_gate_ref; + std::vector _cl_unixs; + std::vector _cl_nhits; + std::vector _cl_tagger; + std::vector _cl_composition; + std::vector _cl_has_sp; + std::vector _cl_sp_x; + std::vector _cl_sp_ex; + std::vector _cl_sp_y; + std::vector _cl_sp_ey; + std::vector _cl_sp_z; + std::vector _cl_sp_ez; + std::vector _cl_sp_pe; + std::vector _cl_sp_ts0; + std::vector _cl_sp_ts0_rwm_ref; + std::vector _cl_sp_ts0_ptb_hlt_beam_gate_ref; + std::vector _cl_sp_ets0; + std::vector _cl_sp_ts1; + std::vector _cl_sp_ts1_rwm_ref; + std::vector _cl_sp_ts1_ptb_hlt_beam_gate_ref; + std::vector _cl_sp_ets1; + std::vector _cl_sp_complete; + + //track level information + std::vector _tr_start_x; + std::vector _tr_start_y; + std::vector _tr_start_z; + std::vector _tr_end_x; + std::vector _tr_end_y; + std::vector _tr_end_z; + std::vector _tr_dir_x; + std::vector _tr_dir_y; + std::vector _tr_dir_z; + std::vector _tr_ts0; + std::vector _tr_ts0_rwm_ref; + std::vector _tr_ts0_ptb_hlt_beam_gate_ref; + std::vector _tr_ets0; + std::vector _tr_ts1; + std::vector _tr_ts1_rwm_ref; + std::vector _tr_ts1_ptb_hlt_beam_gate_ref; + std::vector _tr_ets1; + std::vector _tr_pe; + std::vector _tr_length; + std::vector _tr_tof; + std::vector _tr_theta; + std::vector _tr_phi; + std::vector _tr_triple; + std::vector _tr_tagger1; + std::vector _tr_tagger2; + std::vector _tr_tagger3; + + std::vector _ptb_hlt_trigger; + std::vector _ptb_hlt_timestamp; + + std::vector _ptb_llt_trigger; + std::vector _ptb_llt_timestamp; + + std::vector _tdc_channel; + std::vector _tdc_timestamp; + std::vector _tdc_offset; + std::vector _tdc_name; + + bool _etrig_good, _rwm_good, _ptb_hlt_beam_gate_good, _crt_t1_reset_good; + double _rwm_etrig_diff, _ptb_hlt_beam_gate_etrig_diff, _rwm_crt_t1_reset_diff, _ptb_hlt_beam_gate_crt_t1_reset_diff, + _rwm_ptb_hlt_beam_gate_diff; + + bool _pmt_st_found_trigger; + double _pmt_st_corrected_peak_time, _pmt_st_corrected_peak_time_rwm_ref; +}; + +sbnd::crt::CRTTopHatAnalysis::CRTTopHatAnalysis(fhicl::ParameterSet const& p) + : EDAnalyzer{p} +{ + fCRTStripHitModuleLabel = p.get("CRTStripHitModuleLabel", "crtstrips"); + fCRTClusterModuleLabel = p.get("CRTClusterModuleLabel", "crtclustering"); + fCRTSpacePointModuleLabel = p.get("CRTSpacePointModuleLabel", "crtspacepoints"); + fCRTTrackModuleLabel = p.get("CRTTrackModuleLabel", "crttracks"); + fPTBModuleLabel = p.get("PTBModuleLabel", "ptbdecoder"); + fTDCModuleLabel = p.get("TDCModuleLabel", "tdcdecoder"); + fTimingReferenceModuleLabel = p.get("TimingReferenceModuleLabel", "crtstrips"); + fPMTSoftwareTriggerModuleLabel = p.get("PMTSoftwareTriggerModuleLabel", "pmtmetricbnblight"); + fDebug = p.get("Debug", false); + fCutT0 = p.get("CutT0", false); + fSavePMTSoftwareTrigger = p.get("SavePMTSoftwareTrigger", false); + fMinT0 = p.get("MinT0", std::numeric_limits::min()); + fMaxT0 = p.get("MaxT0", std::numeric_limits::max()); + fAllowedPTBHLTs = p.get>("AllowedPTBHLTs", { 26, 27 }); + + art::ServiceHandle fs; + + fTree = fs->make("tree",""); + fTree->Branch("run", &_run); + fTree->Branch("subrun", &_subrun); + fTree->Branch("event", &_event); + fTree->Branch("crt_timing_reference_type", &_crt_timing_reference_type); + fTree->Branch("crt_timing_reference_channel", &_crt_timing_reference_channel); + + fTree->Branch("sh_channel", "std::vector", &_sh_channel); + fTree->Branch("sh_tagger", "std::vector", &_sh_tagger); + fTree->Branch("sh_ts0", "std::vector", &_sh_ts0); + fTree->Branch("sh_ts0_rwm_ref", "std::vector", &_sh_ts0_rwm_ref); + fTree->Branch("sh_ts0_ptb_hlt_beam_gate_ref", "std::vector", &_sh_ts0_ptb_hlt_beam_gate_ref); + fTree->Branch("sh_ts1", "std::vector", &_sh_ts1); + fTree->Branch("sh_ts1_rwm_ref", "std::vector", &_sh_ts1_rwm_ref); + fTree->Branch("sh_ts1_ptb_hlt_beam_gate_ref", "std::vector", &_sh_ts1_ptb_hlt_beam_gate_ref); + fTree->Branch("sh_unixs", "std::vector", &_sh_unixs); + fTree->Branch("sh_pos", "std::vector", &_sh_pos); + fTree->Branch("sh_err", "std::vector", &_sh_err); + fTree->Branch("sh_adc1", "std::vector", &_sh_adc1); + fTree->Branch("sh_adc2", "std::vector", &_sh_adc2); + fTree->Branch("sh_saturated1", "std::vector", &_sh_saturated1); + fTree->Branch("sh_saturated2", "std::vector", &_sh_saturated2); + + fTree->Branch("cl_ts0", "std::vector", &_cl_ts0); + fTree->Branch("cl_ts0_rwm_ref", "std::vector", &_cl_ts0_rwm_ref); + fTree->Branch("cl_ts0_ptb_hlt_beam_gate_ref", "std::vector", &_cl_ts0_ptb_hlt_beam_gate_ref); + fTree->Branch("cl_ts1", "std::vector", &_cl_ts1); + fTree->Branch("cl_ts1_rwm_ref", "std::vector", &_cl_ts1_rwm_ref); + fTree->Branch("cl_ts1_ptb_hlt_beam_gate_ref", "std::vector", &_cl_ts1_ptb_hlt_beam_gate_ref); + fTree->Branch("cl_unixs", "std::vector", &_cl_unixs); + fTree->Branch("cl_nhits", "std::vector", &_cl_nhits); + fTree->Branch("cl_tagger", "std::vector", &_cl_tagger); + fTree->Branch("cl_composition", "std::vector", &_cl_composition); + fTree->Branch("cl_has_sp", "std::vector", &_cl_has_sp); + fTree->Branch("cl_sp_x", "std::vector", &_cl_sp_x); + fTree->Branch("cl_sp_ex", "std::vector", &_cl_sp_ex); + fTree->Branch("cl_sp_y", "std::vector", &_cl_sp_y); + fTree->Branch("cl_sp_ey", "std::vector", &_cl_sp_ey); + fTree->Branch("cl_sp_z", "std::vector", &_cl_sp_z); + fTree->Branch("cl_sp_ez", "std::vector", &_cl_sp_ez); + fTree->Branch("cl_sp_pe", "std::vector", &_cl_sp_pe); + fTree->Branch("cl_sp_ts0", "std::vector", &_cl_sp_ts0); + fTree->Branch("cl_sp_ts0_rwm_ref", "std::vector", &_cl_sp_ts0_rwm_ref); + fTree->Branch("cl_sp_ts0_ptb_hlt_beam_gate_ref", "std::vector", &_cl_sp_ts0_ptb_hlt_beam_gate_ref); + fTree->Branch("cl_sp_ets0", "std::vector", &_cl_sp_ets0); + fTree->Branch("cl_sp_ts1", "std::vector", &_cl_sp_ts1); + fTree->Branch("cl_sp_ts1_rwm_ref", "std::vector", &_cl_sp_ts1_rwm_ref); + fTree->Branch("cl_sp_ts1_ptb_hlt_beam_gate_ref", "std::vector", &_cl_sp_ts1_ptb_hlt_beam_gate_ref); + fTree->Branch("cl_sp_ets1", "std::vector", &_cl_sp_ets1); + fTree->Branch("cl_sp_complete", "std::vector", &_cl_sp_complete); + + fTree->Branch("tr_start_x", "std::vector", &_tr_start_x); + fTree->Branch("tr_start_y", "std::vector", &_tr_start_y); + fTree->Branch("tr_start_z", "std::vector", &_tr_start_z); + fTree->Branch("tr_end_x", "std::vector", &_tr_end_x); + fTree->Branch("tr_end_y", "std::vector", &_tr_end_y); + fTree->Branch("tr_end_z", "std::vector", &_tr_end_z); + fTree->Branch("tr_dir_x", "std::vector", &_tr_dir_x); + fTree->Branch("tr_dir_y", "std::vector", &_tr_dir_y); + fTree->Branch("tr_dir_z", "std::vector", &_tr_dir_z); + fTree->Branch("tr_ts0", "std::vector", &_tr_ts0); + fTree->Branch("tr_ts0_rwm_ref", "std::vector", &_tr_ts0_rwm_ref); + fTree->Branch("tr_ts0_ptb_hlt_beam_gate_ref", "std::vector", &_tr_ts0_ptb_hlt_beam_gate_ref); + fTree->Branch("tr_ets0", "std::vector", &_tr_ets0); + fTree->Branch("tr_ts1", "std::vector", &_tr_ts1); + fTree->Branch("tr_ts1_rwm_ref", "std::vector", &_tr_ts1_rwm_ref); + fTree->Branch("tr_ts1_ptb_hlt_beam_gate_ref", "std::vector", &_tr_ts1_ptb_hlt_beam_gate_ref); + fTree->Branch("tr_ets1", "std::vector", &_tr_ets1); + fTree->Branch("tr_pe", "std::vector", &_tr_pe); + fTree->Branch("tr_length", "std::vector", &_tr_length); + fTree->Branch("tr_tof", "std::vector", &_tr_tof); + fTree->Branch("tr_theta", "std::vector", &_tr_theta); + fTree->Branch("tr_phi", "std::vector", &_tr_phi); + fTree->Branch("tr_triple", "std::vector", &_tr_triple); + fTree->Branch("tr_tagger1", "std::vector", &_tr_tagger1); + fTree->Branch("tr_tagger2", "std::vector", &_tr_tagger2); + fTree->Branch("tr_tagger3", "std::vector", &_tr_tagger3); + + fTree->Branch("ptb_hlt_trigger", "std::vector", &_ptb_hlt_trigger); + fTree->Branch("ptb_hlt_timestamp", "std::vector", &_ptb_hlt_timestamp); + fTree->Branch("ptb_llt_trigger", "std::vector", &_ptb_llt_trigger); + fTree->Branch("ptb_llt_timestamp", "std::vector", &_ptb_llt_timestamp); + + fTree->Branch("tdc_channel", "std::vector", &_tdc_channel); + fTree->Branch("tdc_timestamp", "std::vector", &_tdc_timestamp); + fTree->Branch("tdc_offset", "std::vector", &_tdc_offset); + fTree->Branch("tdc_name", "std::vector", &_tdc_name); + + fTree->Branch("etrig_good", &_etrig_good); + fTree->Branch("rwm_good", &_rwm_good); + fTree->Branch("ptb_hlt_beam_gate_good", &_ptb_hlt_beam_gate_good); + fTree->Branch("crt_t1_reset_good", &_crt_t1_reset_good); + fTree->Branch("rwm_etrig_diff", &_rwm_etrig_diff); + fTree->Branch("ptb_hlt_beam_gate_etrig_diff", &_ptb_hlt_beam_gate_etrig_diff); + fTree->Branch("rwm_crt_t1_reset_diff", &_rwm_crt_t1_reset_diff); + fTree->Branch("ptb_hlt_beam_gate_crt_t1_reset_diff", &_ptb_hlt_beam_gate_crt_t1_reset_diff); + fTree->Branch("rwm_ptb_hlt_beam_gate_diff", &_rwm_ptb_hlt_beam_gate_diff); + + if(fSavePMTSoftwareTrigger) + { + fTree->Branch("pmt_st_found_trigger", &_pmt_st_found_trigger); + fTree->Branch("pmt_st_corrected_peak_time", &_pmt_st_corrected_peak_time); + fTree->Branch("pmt_st_corrected_peak_time", &_pmt_st_corrected_peak_time); + fTree->Branch("pmt_st_corrected_peak_time_rwm_ref", &_pmt_st_corrected_peak_time_rwm_ref); + } +} + +void sbnd::crt::CRTTopHatAnalysis::analyze(art::Event const& e) +{ + _run = e.id().run(); + _subrun = e.id().subRun(); + _event = e.id().event(); + + _crt_timing_reference_type = -1; + _crt_timing_reference_channel = -1; + + art::Handle TimingReferenceHandle; + e.getByLabel(fTimingReferenceModuleLabel, TimingReferenceHandle); + if(TimingReferenceHandle.isValid()) + { + _crt_timing_reference_type = TimingReferenceHandle->timingType; + _crt_timing_reference_channel = TimingReferenceHandle->timingChannel; + } + + // Get PTBs + art::Handle> PTBHandle; + e.getByLabel(fPTBModuleLabel, PTBHandle); + if(!PTBHandle.isValid()){ + std::cout << "PTB product " << fPTBModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + std::vector> PTBVec; + art::fill_ptr_vector(PTBVec, PTBHandle); + + // Fill PTB variables + AnalysePTBs(PTBVec); + + // Get TDCs + art::Handle> TDCHandle; + e.getByLabel(fTDCModuleLabel, TDCHandle); + if(!TDCHandle.isValid()){ + std::cout << "TDC product " << fTDCModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + std::vector> TDCVec; + art::fill_ptr_vector(TDCVec, TDCHandle); + + // Fill TDC variables + AnalyseTDCs(TDCVec); + + SortReferencing(); + + // Get CRTStripHits + art::Handle> CRTStripHitHandle; + e.getByLabel(fCRTStripHitModuleLabel, CRTStripHitHandle); + if(!CRTStripHitHandle.isValid()){ + std::cout << "CRTStripHit product " << fCRTStripHitModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + std::vector> CRTStripHitVec; + art::fill_ptr_vector(CRTStripHitVec, CRTStripHitHandle); + + // Fill CRTStripHit variables + AnalyseCRTStripHits(e, CRTStripHitVec); + + // Get CRTClusters + art::Handle> CRTClusterHandle; + e.getByLabel(fCRTClusterModuleLabel, CRTClusterHandle); + if(!CRTClusterHandle.isValid()){ + std::cout << "CRTCluster product " << fCRTClusterModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + std::vector> CRTClusterVec; + art::fill_ptr_vector(CRTClusterVec, CRTClusterHandle); + + // Get CRTCluster to CRTSpacePoint Assns + art::FindManyP clustersToSpacePoints(CRTClusterHandle, e, fCRTSpacePointModuleLabel); + + // Fill CRTCluster variables + AnalyseCRTClusters(e, CRTClusterVec, clustersToSpacePoints); + + // Get CRTTracks + art::Handle> CRTTrackHandle; + e.getByLabel(fCRTTrackModuleLabel, CRTTrackHandle); + if(!CRTTrackHandle.isValid()){ + std::cout << "CRTTrack product " << fCRTTrackModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + std::vector> CRTTrackVec; + art::fill_ptr_vector(CRTTrackVec, CRTTrackHandle); + + // Fill CRTTrack variables + AnalyseCRTTracks(e, CRTTrackVec); + + if(fSavePMTSoftwareTrigger) + { + // Get PMTSoftwareTriggers + art::Handle> PMTSoftwareTriggerHandle; + e.getByLabel(fPMTSoftwareTriggerModuleLabel, PMTSoftwareTriggerHandle); + if(!PMTSoftwareTriggerHandle.isValid()){ + std::cout << "PMTSoftwareTrigger product " << fPMTSoftwareTriggerModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + std::vector> PMTSoftwareTriggerVec; + art::fill_ptr_vector(PMTSoftwareTriggerVec, PMTSoftwareTriggerHandle); + + // Fill PMTSoftwareTrigger variables + AnalysePMTSoftwareTriggers(e, PMTSoftwareTriggerVec); + } + + fTree->Fill(); +} + +void sbnd::crt::CRTTopHatAnalysis::AnalysePTBs(std::vector> &PTBVec) +{ + unsigned nHLTs = 0; + + for(auto const& ptb : PTBVec) + nHLTs += ptb->GetNHLTriggers(); + + _ptb_hlt_trigger.resize(nHLTs); + _ptb_hlt_timestamp.resize(nHLTs); + + unsigned hlt_i = 0; + + for(auto const& ptb : PTBVec) + { + for(unsigned i = 0; i < ptb->GetNHLTriggers(); ++i) + { + _ptb_hlt_trigger[hlt_i] = ptb->GetHLTrigger(i).trigger_word; + _ptb_hlt_timestamp[hlt_i] = ptb->GetHLTrigger(i).timestamp * 20; + + ++hlt_i; + } + } + + unsigned nLLTs = 0; + + for(auto const& ptb : PTBVec) + nLLTs += ptb->GetNLLTriggers(); + + _ptb_llt_trigger.resize(nLLTs); + _ptb_llt_timestamp.resize(nLLTs); + + unsigned llt_i = 0; + + for(auto const& ptb : PTBVec) + { + for(unsigned i = 0; i < ptb->GetNLLTriggers(); ++i) + { + _ptb_llt_trigger[llt_i] = ptb->GetLLTrigger(i).trigger_word; + _ptb_llt_timestamp[llt_i] = ptb->GetLLTrigger(i).timestamp * 20; + + ++llt_i; + } + } +} + +void sbnd::crt::CRTTopHatAnalysis::AnalyseTDCs(std::vector> &TDCVec) +{ + const unsigned nTDCs = TDCVec.size(); + + _tdc_channel.resize(nTDCs); + _tdc_timestamp.resize(nTDCs); + _tdc_offset.resize(nTDCs); + _tdc_name.resize(nTDCs); + + unsigned tdc_i = 0; + + for(auto const& tdc : TDCVec) + { + _tdc_channel[tdc_i] = tdc->Channel(); + _tdc_timestamp[tdc_i] = tdc->Timestamp(); + _tdc_offset[tdc_i] = tdc->Offset(); + _tdc_name[tdc_i] = tdc->Name(); + + ++tdc_i; + } +} + +void sbnd::crt::CRTTopHatAnalysis::SortReferencing() +{ + _etrig_good = false; _rwm_good = false; _ptb_hlt_beam_gate_good = false; _crt_t1_reset_good = false; + _rwm_etrig_diff = std::numeric_limits::max(); _ptb_hlt_beam_gate_etrig_diff = std::numeric_limits::max(); + _rwm_crt_t1_reset_diff = std::numeric_limits::max(); _ptb_hlt_beam_gate_crt_t1_reset_diff = std::numeric_limits::max(); + _rwm_ptb_hlt_beam_gate_diff = std::numeric_limits::max(); + + int etrig_count = 0, etrig_id = -1, rwm_count = 0, rwm_id = -1, crt_t1_reset_count = 0, crt_t1_reset_id = -1; + + for(unsigned int tdc_i = 0; tdc_i < _tdc_channel.size(); ++tdc_i) + { + if(_tdc_channel[tdc_i] == 4) + { + ++etrig_count; + etrig_id = tdc_i; + } + else if(_tdc_channel[tdc_i] == 2) + { + ++rwm_count; + rwm_id = tdc_i; + } + else if(_tdc_channel[tdc_i] == 0) + { + ++crt_t1_reset_count; + crt_t1_reset_id = tdc_i; + } + } + + uint64_t etrig = std::numeric_limits::max(), rwm = std::numeric_limits::max(), + hlt = std::numeric_limits::max(), crt_t1_reset = std::numeric_limits::max(); + + if(etrig_count == 1) + { + _etrig_good = true; + etrig = _tdc_timestamp[etrig_id]; + } + + if(rwm_count == 1) + { + _rwm_good = true; + rwm = _tdc_timestamp[rwm_id]; + } + + if(etrig_count == 1) + { + double closest_diff = std::numeric_limits::max(); + + for(unsigned int ptb_i = 0; ptb_i < _ptb_hlt_trigger.size(); ++ptb_i) + { + std::bitset<32> hlt_bitmask = std::bitset<32>(_ptb_hlt_trigger[ptb_i]); + + for(uint32_t allowed_hlt : fAllowedPTBHLTs) + { + if(hlt_bitmask[allowed_hlt]) + { + _ptb_hlt_beam_gate_good = true; + + uint64_t temp_hlt = _ptb_hlt_timestamp[ptb_i]; + double diff = etrig > temp_hlt ? etrig - temp_hlt : -1. * (temp_hlt - etrig); + + if(std::abs(diff) < closest_diff) + { + closest_diff = diff; + hlt = temp_hlt; + } + } + } + } + } + + if(crt_t1_reset_count == 1) + { + _crt_t1_reset_good = true; + crt_t1_reset = _tdc_timestamp[crt_t1_reset_id]; + } + + if(_etrig_good && _rwm_good) + _rwm_etrig_diff = etrig > rwm ? etrig - rwm : -1. * (rwm - etrig); + + if(_etrig_good && _ptb_hlt_beam_gate_good) + _ptb_hlt_beam_gate_etrig_diff = etrig > hlt ? etrig - hlt : -1. * (hlt - etrig); + + if(_crt_t1_reset_good && _rwm_good) + _rwm_crt_t1_reset_diff = crt_t1_reset > rwm ? crt_t1_reset - rwm : -1. * (rwm - crt_t1_reset); + + if(_etrig_good && _crt_t1_reset_good && _ptb_hlt_beam_gate_good) + _ptb_hlt_beam_gate_crt_t1_reset_diff = crt_t1_reset > hlt ? crt_t1_reset - hlt : -1. * (hlt - crt_t1_reset); + + if(_etrig_good && _rwm_good && _ptb_hlt_beam_gate_good) + _rwm_ptb_hlt_beam_gate_diff = hlt > rwm ? hlt - rwm : -1. * (rwm - hlt); +} + +void sbnd::crt::CRTTopHatAnalysis::AnalyseCRTStripHits(const art::Event &e, const std::vector> &CRTStripHitVec) +{ + _sh_channel.clear(); + _sh_tagger.clear(); + _sh_ts0.clear(); + _sh_ts0_rwm_ref.clear(); + _sh_ts0_ptb_hlt_beam_gate_ref.clear(); + _sh_ts1.clear(); + _sh_ts1_rwm_ref.clear(); + _sh_ts1_ptb_hlt_beam_gate_ref.clear(); + _sh_unixs.clear(); + _sh_pos.clear(); + _sh_err.clear(); + _sh_adc1.clear(); + _sh_adc2.clear(); + _sh_saturated1.clear(); + _sh_saturated2.clear(); + + for(auto const &hit : CRTStripHitVec) + { + if(fCutT0 && (hit->Ts0() < fMinT0 || hit->Ts0() > fMaxT0)) + continue; + + _sh_channel.push_back(hit->Channel()); + _sh_tagger.push_back(fCRTGeoService->ChannelToTaggerEnum(hit->Channel())); + _sh_ts0.push_back(hit->Ts0()); + _sh_ts0_rwm_ref.push_back(hit->Ts0() + _rwm_etrig_diff); + _sh_ts0_ptb_hlt_beam_gate_ref.push_back(hit->Ts0() + _ptb_hlt_beam_gate_etrig_diff); + _sh_ts1.push_back(hit->Ts1()); + _sh_ts1_rwm_ref.push_back(hit->Ts1() + _rwm_crt_t1_reset_diff); + _sh_ts1_ptb_hlt_beam_gate_ref.push_back(hit->Ts1() + _ptb_hlt_beam_gate_crt_t1_reset_diff); + _sh_unixs.push_back(hit->UnixS()); + _sh_pos.push_back(hit->Pos()); + _sh_err.push_back(hit->Error()); + _sh_adc1.push_back(hit->ADC1()); + _sh_adc2.push_back(hit->ADC2()); + _sh_saturated1.push_back(hit->Saturated1()); + _sh_saturated2.push_back(hit->Saturated2()); + } +} + +void sbnd::crt::CRTTopHatAnalysis::AnalyseCRTClusters(const art::Event &e, const std::vector> &CRTClusterVec, + const art::FindManyP &clustersToSpacePoints) +{ + _cl_ts0.clear(); + _cl_ts0_rwm_ref.clear(); + _cl_ts0_ptb_hlt_beam_gate_ref.clear(); + _cl_ts1.clear(); + _cl_ts1_rwm_ref.clear(); + _cl_ts1_ptb_hlt_beam_gate_ref.clear(); + _cl_unixs.clear(); + _cl_nhits.clear(); + _cl_tagger.clear(); + _cl_composition.clear(); + _cl_has_sp.clear(); + _cl_sp_x.clear(); + _cl_sp_ex.clear(); + _cl_sp_y.clear(); + _cl_sp_ey.clear(); + _cl_sp_z.clear(); + _cl_sp_ez.clear(); + _cl_sp_pe.clear(); + _cl_sp_ts0.clear(); + _cl_sp_ts0_rwm_ref.clear(); + _cl_sp_ts0_ptb_hlt_beam_gate_ref.clear(); + _cl_sp_ets0.clear(); + _cl_sp_ts1.clear(); + _cl_sp_ts1_rwm_ref.clear(); + _cl_sp_ts1_ptb_hlt_beam_gate_ref.clear(); + _cl_sp_ets1.clear(); + _cl_sp_complete.clear(); + + for(auto const &cluster : CRTClusterVec) + { + if(fCutT0 && (cluster->Ts0() < fMinT0 || cluster->Ts0() > fMaxT0)) + continue; + + _cl_ts0.push_back(cluster->Ts0()); + _cl_ts0_rwm_ref.push_back(cluster->Ts0() + _rwm_etrig_diff); + _cl_ts0_ptb_hlt_beam_gate_ref.push_back(cluster->Ts0() + _ptb_hlt_beam_gate_etrig_diff); + _cl_ts1.push_back(cluster->Ts1()); + _cl_ts1_rwm_ref.push_back(cluster->Ts1() + _rwm_crt_t1_reset_diff); + _cl_ts1_ptb_hlt_beam_gate_ref.push_back(cluster->Ts1() + _ptb_hlt_beam_gate_crt_t1_reset_diff); + _cl_unixs.push_back(cluster->UnixS()); + _cl_nhits.push_back(cluster->NHits()); + _cl_tagger.push_back(cluster->Tagger()); + _cl_composition.push_back(cluster->Composition()); + + const auto spacepoints = clustersToSpacePoints.at(cluster.key()); + if(spacepoints.size() == 1) + { + const auto spacepoint = spacepoints[0]; + + _cl_has_sp.push_back(true); + _cl_sp_x.push_back(spacepoint->X()); + _cl_sp_ex.push_back(spacepoint->XErr()); + _cl_sp_y.push_back(spacepoint->Y()); + _cl_sp_ey.push_back(spacepoint->YErr()); + _cl_sp_z.push_back(spacepoint->Z()); + _cl_sp_ez.push_back(spacepoint->ZErr()); + _cl_sp_pe.push_back(spacepoint->PE()); + _cl_sp_ts0.push_back(spacepoint->Ts0()); + _cl_sp_ts0_rwm_ref.push_back(spacepoint->Ts0() + _rwm_etrig_diff); + _cl_sp_ts0_ptb_hlt_beam_gate_ref.push_back(spacepoint->Ts0() + _ptb_hlt_beam_gate_etrig_diff); + _cl_sp_ets0.push_back(spacepoint->Ts0Err()); + _cl_sp_ts1.push_back(spacepoint->Ts1()); + _cl_sp_ts1_rwm_ref.push_back(spacepoint->Ts1() + _rwm_crt_t1_reset_diff); + _cl_sp_ts1_ptb_hlt_beam_gate_ref.push_back(spacepoint->Ts1() + _ptb_hlt_beam_gate_crt_t1_reset_diff); + _cl_sp_ets1.push_back(spacepoint->Ts1Err()); + _cl_sp_complete.push_back(spacepoint->Complete()); + } + else + { + _cl_has_sp.push_back(false); + _cl_sp_x.push_back(-999999.); + _cl_sp_ex.push_back(-999999.); + _cl_sp_y.push_back(-999999.); + _cl_sp_ey.push_back(-999999.); + _cl_sp_z.push_back(-999999.); + _cl_sp_ez.push_back(-999999.); + _cl_sp_pe.push_back(-999999.); + _cl_sp_ts0.push_back(-999999.); + _cl_sp_ts0_rwm_ref.push_back(-999999.); + _cl_sp_ts0_ptb_hlt_beam_gate_ref.push_back(-999999.); + _cl_sp_ets0.push_back(-999999.); + _cl_sp_ts1.push_back(-999999.); + _cl_sp_ts1_rwm_ref.push_back(-999999.); + _cl_sp_ts1_ptb_hlt_beam_gate_ref.push_back(-999999.); + _cl_sp_ets1.push_back(-999999.); + _cl_sp_complete.push_back(false); + } + } +} +void sbnd::crt::CRTTopHatAnalysis::AnalyseCRTTracks(const art::Event &e, const std::vector> &CRTTrackVec) +{ + _tr_start_x.clear(); + _tr_start_y.clear(); + _tr_start_z.clear(); + _tr_end_x.clear(); + _tr_end_y.clear(); + _tr_end_z.clear(); + _tr_dir_x.clear(); + _tr_dir_y.clear(); + _tr_dir_z.clear(); + _tr_ts0.clear(); + _tr_ts0_rwm_ref.clear(); + _tr_ts0_ptb_hlt_beam_gate_ref.clear(); + _tr_ets0.clear(); + _tr_ts1.clear(); + _tr_ts1_rwm_ref.clear(); + _tr_ts1_ptb_hlt_beam_gate_ref.clear(); + _tr_ets1.clear(); + _tr_pe.clear(); + _tr_length.clear(); + _tr_tof.clear(); + _tr_theta.clear(); + _tr_phi.clear(); + _tr_triple.clear(); + _tr_tagger1.clear(); + _tr_tagger2.clear(); + _tr_tagger3.clear(); + + for(auto const& track : CRTTrackVec) + { + if(fCutT0 && (track->Ts0() < fMinT0 || track->Ts0() > fMaxT0)) + continue; + + const geo::Point_t start = track->Start(); + _tr_start_x.push_back(start.X()); + _tr_start_y.push_back(start.Y()); + _tr_start_z.push_back(start.Z()); + + const geo::Point_t end = track->End(); + _tr_end_x.push_back(end.X()); + _tr_end_y.push_back(end.Y()); + _tr_end_z.push_back(end.Z()); + + const geo::Vector_t dir = track->Direction(); + _tr_dir_x.push_back(dir.X()); + _tr_dir_y.push_back(dir.Y()); + _tr_dir_z.push_back(dir.Z()); + + _tr_ts0.push_back(track->Ts0()); + _tr_ts0_rwm_ref.push_back(track->Ts0() + _rwm_etrig_diff); + _tr_ts0_ptb_hlt_beam_gate_ref.push_back(track->Ts0() + _ptb_hlt_beam_gate_etrig_diff); + _tr_ets0.push_back(track->Ts0Err()); + _tr_ts1.push_back(track->Ts1()); + _tr_ts1_rwm_ref.push_back(track->Ts1() + _rwm_crt_t1_reset_diff); + _tr_ts1_ptb_hlt_beam_gate_ref.push_back(track->Ts1() + _ptb_hlt_beam_gate_crt_t1_reset_diff); + _tr_ets1.push_back(track->Ts1Err()); + _tr_pe.push_back(track->PE()); + _tr_length.push_back(track->Length()); + _tr_tof.push_back(track->ToF()); + _tr_theta.push_back(TMath::RadToDeg() * track->Theta()); + _tr_phi.push_back(TMath::RadToDeg() * track->Phi()); + _tr_triple.push_back(track->Triple()); + + unsigned tag_i = 0; + + for(auto const &tagger : track->Taggers()) + { + if(tag_i == 0) + _tr_tagger1.push_back(tagger); + else if(tag_i == 1) + _tr_tagger2.push_back(tagger); + else if(tag_i == 2) + _tr_tagger3.push_back(tagger); + + ++tag_i; + } + } +} + +void sbnd::crt::CRTTopHatAnalysis::AnalysePMTSoftwareTriggers(const art::Event &e, const std::vector> &PMTSoftwareTriggerVec) +{ + _pmt_st_found_trigger = false; + _pmt_st_corrected_peak_time = std::numeric_limits::lowest(); + _pmt_st_corrected_peak_time_rwm_ref = std::numeric_limits::lowest(); + + if(PMTSoftwareTriggerVec.size() != 1) + return; + + _pmt_st_found_trigger = PMTSoftwareTriggerVec[0]->foundBeamTrigger; + _pmt_st_corrected_peak_time = PMTSoftwareTriggerVec[0]->peaktime*1e3 + PMTSoftwareTriggerVec[0]->trig_ts; + _pmt_st_corrected_peak_time_rwm_ref = _pmt_st_corrected_peak_time + _rwm_ptb_hlt_beam_gate_diff; +} + +DEFINE_ART_MODULE(sbnd::crt::CRTTopHatAnalysis) diff --git a/sbndcode/CRT/CRTAna/crttophatana_sbnd.fcl b/sbndcode/CRT/CRTAna/crttophatana_sbnd.fcl new file mode 100644 index 000000000..a82b14e43 --- /dev/null +++ b/sbndcode/CRT/CRTAna/crttophatana_sbnd.fcl @@ -0,0 +1,12 @@ +BEGIN_PROLOG + +crttophatana_data_sbnd: +{ + module_type: "CRTTopHatAnalysis" + CutT0: true + MinT0: -50000 + MaxT0: 50000 + SavePMTSoftwareTrigger: true +} + +END_PROLOG diff --git a/sbndcode/CRT/CRTAna/run_crttophatana_data.fcl b/sbndcode/CRT/CRTAna/run_crttophatana_data.fcl new file mode 100644 index 000000000..cce367369 --- /dev/null +++ b/sbndcode/CRT/CRTAna/run_crttophatana_data.fcl @@ -0,0 +1,28 @@ +#include "services_sbnd.fcl" +#include "crt_services_sbnd.fcl" +#include "crttophatana_sbnd.fcl" + +process_name: CRTTopHatAna + +services: +{ + TFileService: { fileName: "crttophatana_sbnd.root" } + @table::sbnd_basic_services + @table::crt_services_data_sbnd +} + +source: +{ + module_type: RootInput +} + +physics: +{ + analyzers: + { + crttophatana: @local::crttophatana_data_sbnd + } + + ana: [ crttophatana ] + end_paths: [ ana ] +} From c752a9148a7b92b38fcff9c3bfc6c8360df0ad88 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Mon, 23 Feb 2026 08:15:52 -0600 Subject: [PATCH 11/31] Add relevant functions for ADRIFT to GeoService --- .../Geometry/GeometryWrappers/CRTGeoService.h | 4 ++++ .../GeometryWrappers/CRTGeoService_service.cc | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/sbndcode/Geometry/GeometryWrappers/CRTGeoService.h b/sbndcode/Geometry/GeometryWrappers/CRTGeoService.h index 7b76b4fb0..c60b95b80 100644 --- a/sbndcode/Geometry/GeometryWrappers/CRTGeoService.h +++ b/sbndcode/Geometry/GeometryWrappers/CRTGeoService.h @@ -430,6 +430,10 @@ namespace sbnd::crt { bool IsPointInsideCRTLimits(const geo::Point_t &point); + double StripArea(const uint16_t channel); + + double StripAverageY(const uint16_t channel); + private: std::map fTaggers; diff --git a/sbndcode/Geometry/GeometryWrappers/CRTGeoService_service.cc b/sbndcode/Geometry/GeometryWrappers/CRTGeoService_service.cc index a8b64a01b..76be4b46f 100644 --- a/sbndcode/Geometry/GeometryWrappers/CRTGeoService_service.cc +++ b/sbndcode/Geometry/GeometryWrappers/CRTGeoService_service.cc @@ -562,6 +562,24 @@ namespace sbnd::crt { (point.Y() > lims[1] && point.Y() < lims[4]) && (point.Z() > lims[2] && point.Z() < lims[5]); } + + double CRTGeoService::StripArea(const uint16_t channel) + { + CRTStripGeo strip = GetStrip(channel); + const double x = abs(strip.maxX - strip.minX) / 2; + const double y = abs(strip.maxY - strip.minY) / 2; + const double z = abs(strip.maxZ - strip.minZ) / 2; + + // One will be 1cm so this gives the area in cm^2 + return x * y * z; + } + + double CRTGeoService::StripAverageY(const uint16_t channel) + { + CRTStripGeo strip = GetStrip(channel); + + return (strip.maxY + strip.minY) / 2; + } } DEFINE_ART_SERVICE(sbnd::crt::CRTGeoService) From 263176b4c4c419975ac68a6690febfe7e47d510d Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Tue, 24 Feb 2026 06:47:03 -0600 Subject: [PATCH 12/31] Add skeleton for timing analysis --- sbndcode/CRT/CRTAna/CMakeLists.txt | 1 + .../CRT/CRTAna/CRTTimingAnalysis_module.cc | 666 ++++++++++++++++++ sbndcode/CRT/CRTAna/crttimingana_sbnd.fcl | 19 + 3 files changed, 686 insertions(+) create mode 100644 sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc create mode 100644 sbndcode/CRT/CRTAna/crttimingana_sbnd.fcl diff --git a/sbndcode/CRT/CRTAna/CMakeLists.txt b/sbndcode/CRT/CRTAna/CMakeLists.txt index 2cbcc6327..05de4d016 100644 --- a/sbndcode/CRT/CRTAna/CMakeLists.txt +++ b/sbndcode/CRT/CRTAna/CMakeLists.txt @@ -8,6 +8,7 @@ art_make( sbndaq_artdaq_core::sbndaq-artdaq-core_Obj_SBND sbnobj::SBND_CRT sbnobj::SBND_Timing + sbnobj::Common_Reco sbndcode_CRT_CRTBackTracker ) diff --git a/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc b/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc new file mode 100644 index 000000000..3fa9d0fd6 --- /dev/null +++ b/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc @@ -0,0 +1,666 @@ +//////////////////////////////////////////////////////////////////////// +// Class: CRTTimingAnalysis +// Plugin Type: analyzer +// File: CRTTimingAnalysis_module.cc +// Author: Henry Lay (h.lay@sheffield.ac.uk) +//////////////////////////////////////////////////////////////////////// + +#include "art/Framework/Core/EDAnalyzer.h" +#include "art/Framework/Core/ModuleMacros.h" +#include "art/Framework/Principal/Event.h" +#include "art/Framework/Principal/Handle.h" +#include "art/Framework/Principal/Run.h" +#include "art/Framework/Principal/SubRun.h" +#include "canvas/Utilities/InputTag.h" +#include "fhiclcpp/ParameterSet.h" +#include "messagefacility/MessageLogger/MessageLogger.h" +#include "art_root_io/TFileService.h" +#include "canvas/Persistency/Common/FindManyP.h" +#include "canvas/Persistency/Common/FindOneP.h" + +#include "TTree.h" + +#include "lardataobj/RecoBase/Slice.h" +#include "lardataobj/RecoBase/PFParticle.h" +#include "lardataobj/RecoBase/Track.h" +#include "lardataobj/AnalysisBase/T0.h" + +#include "sbnobj/SBND/CRT/CRTStripHit.hh" +#include "sbnobj/SBND/CRT/CRTCluster.hh" +#include "sbnobj/SBND/CRT/CRTSpacePoint.hh" +#include "sbnobj/SBND/CRT/CRTTrack.hh" +#include "sbnobj/SBND/Timing/DAQTimestamp.hh" +#include "sbnobj/Common/Reco/CorrectedOpFlashTiming.h" + +#include "sbndcode/Geometry/GeometryWrappers/CRTGeoService.h" +#include "sbndcode/Decoders/PTB/sbndptb.h" +#include "sbndcode/Timing/SBNDRawTimingObj.h" + +namespace sbnd::crt { + class CRTTimingAnalysis; +} + +class sbnd::crt::CRTTimingAnalysis : public art::EDAnalyzer { +public: + explicit CRTTimingAnalysis(fhicl::ParameterSet const& p); + // The compiler-generated destructor is fine for non-base + // classes without bare pointers or other resource use. + + // Plugins should not be copied or assigned. + CRTTimingAnalysis(CRTTimingAnalysis const&) = delete; + CRTTimingAnalysis(CRTTimingAnalysis&&) = delete; + CRTTimingAnalysis& operator=(CRTTimingAnalysis const&) = delete; + CRTTimingAnalysis& operator=(CRTTimingAnalysis&&) = delete; + + // Required functions. + void analyze(art::Event const& e) override; + + void AnalysePTBs(std::vector> &PTBVec); + + void AnalyseTDCs(std::vector> &TDCVec); + + void SortReferencing(); + + void AnalyseCRTSpacePoints(const std::vector> &CRTSpacePointVec, + const art::FindOneP &spacepointsToClusters, + const art::FindManyP &clustersToStripHits); + + void AnalyseCRTTracks(const std::vector> &CRTTrackVec, + const art::FindManyP &tracksToSpacePoints, + const art::FindOneP &spacepointsToClusters, + const art::FindManyP &clustersToStripHits); + + void AnalyseTPCSlices(const std::vector> &TPCSliceVec, + const art::FindManyP &sliceToCorrectedOpFlashes, + const art::FindManyP &sliceToPFPs, + const art::FindOneP &pfpToTrack, + const art::FindOneP &trackToCRTSpacePoint, + const art::FindOneP &spacepointsToClusters, + const art::FindManyP &clustersToStripHits); + +private: + + art::ServiceHandle fCRTGeoService; + + // fcl Controlled Variables + std::string fCRTClusterModuleLabel, fCRTSpacePointModuleLabel, fCRTTrackModuleLabel, + fPTBModuleLabel, fTDCModuleLabel, fTimingReferenceModuleLabel, fTPCSliceModuleLabel, + fCorrectedOpFlashModuleLabel, fTPCTrackModuleLabel, fCRTSpacePointMatchingModuleLabel; + std::vector fAllowedPTBHLTs; + + // Global Storage + std::vector _ptb_hlt_trigger; + std::vector _ptb_hlt_timestamp; + + std::vector _ptb_llt_trigger; + std::vector _ptb_llt_timestamp; + + std::vector _tdc_channel; + std::vector _tdc_timestamp; + std::vector _tdc_offset; + std::vector _tdc_name; + + // Trees + TTree *fSPTree, *fTrTree, *fTPCTree; + + // Tree Variables + int _run; + int _subrun; + int _event; + int _crt_timing_reference_type; + int _crt_timing_reference_channel; + + bool _etrig_good; + bool _rwm_good; + bool _ptb_hlt_beam_gate_good; + bool _crt_t1_reset_good; + double _rwm_etrig_diff; + double _ptb_hlt_beam_gate_etrig_diff; + double _rwm_crt_t1_reset_diff; + double _ptb_hlt_beam_gate_crt_t1_reset_diff; + double _rwm_ptb_hlt_beam_gate_diff; + + uint16_t _sp_nhits; + int16_t _sp_tagger; + double _sp_x; + double _sp_y; + double _sp_z; + double _sp_pe; + double _sp_ts0; + double _sp_ts0_rwm_ref; + double _sp_ts0_ptb_hlt_beam_gate_ref; + double _sp_dts0; + double _sp_ts1; + double _sp_ts1_rwm_ref; + double _sp_ts1_ptb_hlt_beam_gate_ref; + double _sp_dts1; + bool _sp_single_timing_chain; + int16_t _sp_timing_chain; + std::vector _sp_sh_channel_set; + std::vector _sp_sh_mac5_set; + std::vector _sp_sh_timing_chain_set; + std::vector _sp_sh_ts0_set; + std::vector _sp_sh_ts1_set; + std::vector _sp_sh_time_walk_set; + std::vector _sp_sh_prop_delay_set; + std::vector _sp_sh_cable_length_set; + std::vector _sp_sh_calib_offset_ts0_set; + std::vector _sp_sh_calib_offset_ts1_set; + + double _tr_start_x; + double _tr_start_y; + double _tr_start_z; + double _tr_end_x; + double _tr_end_y; + double _tr_end_z; + double _tr_dir_x; + double _tr_dir_y; + double _tr_dir_z; + double _tr_ts0; + double _tr_ts0_rwm_ref; + double _tr_ts0_ptb_hlt_beam_gate_ref; + double _tr_ts1; + double _tr_ts1_rwm_ref; + double _tr_ts1_ptb_hlt_beam_gate_ref; + double _tr_pe; + double _tr_length; + double _tr_length_tof; + double _tr_tof_ts0; + double _tr_tof_diff_ts0; + double _tr_tof_ts1; + double _tr_tof_diff_ts1; + double _tr_theta; + double _tr_phi; + bool _tr_triple; + int16_t _tr_tagger1; + int16_t _tr_tagger2; + int16_t _tr_tagger3; + int16_t _tr_start_tagger; + double _tr_start_dts0; + bool _tr_start_single_timing_chain; + int16_t _tr_start_timing_chain; + int16_t _tr_end_tagger; + double _tr_end_dts0; + bool _tr_end_single_timing_chain; + int16_t _tr_end_timing_chain; + + bool _tpc_has_corrected_opflash; + bool _tpc_has_crt_sp_match; + double _tpc_opflash_t0; + double _tpc_opflash_nutof_light; + double _tpc_opflash_nutof_charge; + double _tpc_opflash_t0_corrected; + double _tpc_opflash_t0_corrected_rwm; + double _tpc_crt_sp_score; + double _tpc_crt_sp_ts0; + double _tpc_crt_sp_ts0_rwm_ref; + double _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref; + double _tpc_crt_sp_dts0; + double _tpc_crt_sp_ts1; + double _tpc_crt_sp_ts1_rwm_ref; + double _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref; + double _tpc_crt_sp_dts1; +}; + +sbnd::crt::CRTTimingAnalysis::CRTTimingAnalysis(fhicl::ParameterSet const& p) + : EDAnalyzer{p} +{ + fCRTClusterModuleLabel = p.get("CRTClusterModuleLabel"); + fCRTSpacePointModuleLabel = p.get("CRTSpacePointModuleLabel"); + fCRTTrackModuleLabel = p.get("CRTTrackModuleLabel"); + fPTBModuleLabel = p.get("PTBModuleLabel"); + fTDCModuleLabel = p.get("TDCModuleLabel"); + fTimingReferenceModuleLabel = p.get("TimingReferenceModuleLabel"); + fTPCSliceModuleLabel = p.get("TPCSliceModuleLabel"); + fCorrectedOpFlashModuleLabel = p.get("CorrectedOpFlashModuleLabel"); + fTPCTrackModuleLabel = p.get("TPCTrackModuleLabel"); + fCRTSpacePointMatchingModuleLabel = p.get("CRTSpacePointMatchingModuleLabel"); + fAllowedPTBHLTs = p.get>("AllowedPTBHLTs"); + + art::ServiceHandle fs; + + fSPTree = fs->make("spacepoints",""); + fSPTree->Branch("run", "int", &_run); + fSPTree->Branch("subrun", "int", &_subrun); + fSPTree->Branch("event", "int", &_event); + fSPTree->Branch("crt_timing_reference_type", "int", &_crt_timing_reference_type); + fSPTree->Branch("crt_timing_reference_channel", "int", &_crt_timing_reference_channel); + + fSPTree->Branch("etrig_good", "bool", &_etrig_good); + fSPTree->Branch("rwm_good", "bool", &_rwm_good); + fSPTree->Branch("ptb_hlt_beam_gate_good", "bool", &_ptb_hlt_beam_gate_good); + fSPTree->Branch("crt_t1_reset_good", "bool", &_crt_t1_reset_good); + fSPTree->Branch("rwm_etrig_diff", "double", &_rwm_etrig_diff); + fSPTree->Branch("ptb_hlt_beam_gate_etrig_diff", "double", &_ptb_hlt_beam_gate_etrig_diff); + fSPTree->Branch("rwm_crt_t1_reset_diff", "double", &_rwm_crt_t1_reset_diff); + fSPTree->Branch("ptb_hlt_beam_gate_crt_t1_reset_diff", "double", &_ptb_hlt_beam_gate_crt_t1_reset_diff); + fSPTree->Branch("rwm_ptb_hlt_beam_gate_diff", "double", &_rwm_ptb_hlt_beam_gate_diff); + + fSPTree->Branch("sp_nhits", "uint16_t", &_sp_nhits); + fSPTree->Branch("sp_tagger", "int16_t", &_sp_tagger); + fSPTree->Branch("sp_x", "double", &_sp_x); + fSPTree->Branch("sp_y", "double", &_sp_y); + fSPTree->Branch("sp_z", "double", &_sp_z); + fSPTree->Branch("sp_pe", "double", &_sp_pe); + fSPTree->Branch("sp_ts0", "double", &_sp_ts0); + fSPTree->Branch("sp_ts0_rwm_ref", "double", &_sp_ts0_rwm_ref); + fSPTree->Branch("sp_ts0_ptb_hlt_beam_gate_ref", "double", &_sp_ts0_ptb_hlt_beam_gate_ref); + fSPTree->Branch("sp_dts0", "double", &_sp_dts0); + fSPTree->Branch("sp_ts1", "double", &_sp_ts1); + fSPTree->Branch("sp_ts1_rwm_ref", "double", &_sp_ts1_rwm_ref); + fSPTree->Branch("sp_ts1_ptb_hlt_beam_gate_ref", "double", &_sp_ts1_ptb_hlt_beam_gate_ref); + fSPTree->Branch("sp_dts1", "double", &_sp_dts1); + fSPTree->Branch("sp_single_timing_chain", "bool", &_sp_single_timing_chain); + fSPTree->Branch("sp_timing_chain", "int16_t", &_sp_timing_chain); + fSPTree->Branch("sp_sh_channel_set", "std::vector", &_sp_sh_channel_set); + fSPTree->Branch("sp_sh_mac5_set", "std::vector", &_sp_sh_mac5_set); + fSPTree->Branch("sp_sh_timing_chain_set", "std::vector", &_sp_sh_timing_chain_set); + fSPTree->Branch("sp_sh_ts0_set", "std::vector", &_sp_sh_ts0_set); + fSPTree->Branch("sp_sh_ts1_set", "std::vector", &_sp_sh_ts1_set); + fSPTree->Branch("sp_sh_time_walk_set", "std::vector", &_sp_sh_time_walk_set); + fSPTree->Branch("sp_sh_prop_delay_set", "std::vector", &_sp_sh_prop_delay_set); + fSPTree->Branch("sp_sh_cable_length_set", "std::vector", &_sp_sh_cable_length_set); + fSPTree->Branch("sp_sh_calib_offset_ts0_set", "std::vector", &_sp_sh_calib_offset_ts0_set); + fSPTree->Branch("sp_sh_calib_offset_ts1_set", "std::vector", &_sp_sh_calib_offset_ts1_set); + + fTrTree = fs->make("tracks",""); + fTrTree->Branch("run", "int", &_run); + fTrTree->Branch("subrun", "int", &_subrun); + fTrTree->Branch("event", "int", &_event); + fTrTree->Branch("crt_timing_reference_type", "int", &_crt_timing_reference_type); + fTrTree->Branch("crt_timing_reference_channel", "int", &_crt_timing_reference_channel); + + fTrTree->Branch("etrig_good", "bool", &_etrig_good); + fTrTree->Branch("rwm_good", "bool", &_rwm_good); + fTrTree->Branch("ptb_hlt_beam_gate_good", "bool", &_ptb_hlt_beam_gate_good); + fTrTree->Branch("crt_t1_reset_good", "bool", &_crt_t1_reset_good); + fTrTree->Branch("rwm_etrig_diff", "double", &_rwm_etrig_diff); + fTrTree->Branch("ptb_hlt_beam_gate_etrig_diff", "double", &_ptb_hlt_beam_gate_etrig_diff); + fTrTree->Branch("rwm_crt_t1_reset_diff", "double", &_rwm_crt_t1_reset_diff); + fTrTree->Branch("ptb_hlt_beam_gate_crt_t1_reset_diff", "double", &_ptb_hlt_beam_gate_crt_t1_reset_diff); + fTrTree->Branch("rwm_ptb_hlt_beam_gate_diff", "double", &_rwm_ptb_hlt_beam_gate_diff); + + fTrTree->Branch("tr_start_x", "double", &_tr_start_x); + fTrTree->Branch("tr_start_y", "double", &_tr_start_y); + fTrTree->Branch("tr_start_z", "double", &_tr_start_z); + fTrTree->Branch("tr_end_x", "double", &_tr_end_x); + fTrTree->Branch("tr_end_y", "double", &_tr_end_y); + fTrTree->Branch("tr_end_z", "double", &_tr_end_z); + fTrTree->Branch("tr_dir_x", "double", &_tr_dir_x); + fTrTree->Branch("tr_dir_y", "double", &_tr_dir_y); + fTrTree->Branch("tr_dir_z", "double", &_tr_dir_z); + fTrTree->Branch("tr_ts0", "double", &_tr_ts0); + fTrTree->Branch("tr_ts0_rwm_ref", "double", &_tr_ts0_rwm_ref); + fTrTree->Branch("tr_ts0_ptb_hlt_beam_gate_ref", "double", &_tr_ts0_ptb_hlt_beam_gate_ref); + fTrTree->Branch("tr_ts1", "double", &_tr_ts1); + fTrTree->Branch("tr_ts1_rwm_ref", "double", &_tr_ts1_rwm_ref); + fTrTree->Branch("tr_ts1_ptb_hlt_beam_gate_ref", "double", &_tr_ts1_ptb_hlt_beam_gate_ref); + fTrTree->Branch("tr_pe", "double", &_tr_pe); + fTrTree->Branch("tr_length", "double", &_tr_length); + fTrTree->Branch("tr_length_tof", "double", &_tr_length_tof); + fTrTree->Branch("tr_tof_ts0", "double", &_tr_tof_ts0); + fTrTree->Branch("tr_tof_diff_ts0", "double", &_tr_tof_diff_ts0); + fTrTree->Branch("tr_tof_ts1", "double", &_tr_tof_ts1); + fTrTree->Branch("tr_tof_diff_ts1", "double", &_tr_tof_diff_ts1); + fTrTree->Branch("tr_theta", "double", &_tr_theta); + fTrTree->Branch("tr_phi", "double", &_tr_phi); + fTrTree->Branch("tr_triple", "bool", &_tr_triple); + fTrTree->Branch("tr_tagger1", "int16_t", &_tr_tagger1); + fTrTree->Branch("tr_tagger2", "int16_t", &_tr_tagger2); + fTrTree->Branch("tr_tagger3", "int16_t", &_tr_tagger3); + fTrTree->Branch("tr_start_tagger", "int16_t", &_tr_start_tagger); + fTrTree->Branch("tr_start_dts0", "double", &_tr_start_dts0); + fTrTree->Branch("tr_start_single_timing_chain", "bool", &_tr_start_single_timing_chain); + fTrTree->Branch("tr_start_timing_chain", "int16_t", &_tr_start_timing_chain); + fTrTree->Branch("tr_end_tagger", "int16_t", &_tr_end_tagger); + fTrTree->Branch("tr_end_dts0", "double", &_tr_end_dts0); + fTrTree->Branch("tr_end_single_timing_chain", "bool", &_tr_end_single_timing_chain); + fTrTree->Branch("tr_end_timing_chain", "int16_t", &_tr_end_timing_chain); + + fTPCTree = fs->make("slices",""); + fTPCTree->Branch("run", "int", &_run); + fTPCTree->Branch("subrun", "int", &_subrun); + fTPCTree->Branch("event", "int", &_event); + fTPCTree->Branch("crt_timing_reference_type", "int", &_crt_timing_reference_type); + fTPCTree->Branch("crt_timing_reference_channel", "int", &_crt_timing_reference_channel); + + fTPCTree->Branch("etrig_good", "bool", &_etrig_good); + fTPCTree->Branch("rwm_good", "bool", &_rwm_good); + fTPCTree->Branch("ptb_hlt_beam_gate_good", "bool", &_ptb_hlt_beam_gate_good); + fTPCTree->Branch("crt_t1_reset_good", "bool", &_crt_t1_reset_good); + fTPCTree->Branch("rwm_etrig_diff", "double", &_rwm_etrig_diff); + fTPCTree->Branch("ptb_hlt_beam_gate_etrig_diff", "double", &_ptb_hlt_beam_gate_etrig_diff); + fTPCTree->Branch("rwm_crt_t1_reset_diff", "double", &_rwm_crt_t1_reset_diff); + fTPCTree->Branch("ptb_hlt_beam_gate_crt_t1_reset_diff", "double", &_ptb_hlt_beam_gate_crt_t1_reset_diff); + fTPCTree->Branch("rwm_ptb_hlt_beam_gate_diff", "double", &_rwm_ptb_hlt_beam_gate_diff); + + fTPCTree->Branch("tpc_has_corrected_opflash", "bool", &_tpc_has_corrected_opflash); + fTPCTree->Branch("tpc_has_crt_sp_match", "bool", &_tpc_has_crt_sp_match); + fTPCTree->Branch("tpc_opflash_t0", "double", &_tpc_opflash_t0); + fTPCTree->Branch("tpc_opflash_nutof_light", "double", &_tpc_opflash_nutof_light); + fTPCTree->Branch("tpc_opflash_nutof_charge", "double", &_tpc_opflash_nutof_charge); + fTPCTree->Branch("tpc_opflash_t0_corrected", "double", &_tpc_opflash_t0_corrected); + fTPCTree->Branch("tpc_opflash_t0_corrected_rwm", "double", &_tpc_opflash_t0_corrected_rwm); + fTPCTree->Branch("tpc_crt_sp_score", "double", &_tpc_crt_sp_score); + fTPCTree->Branch("tpc_crt_sp_ts0", "double", &_tpc_crt_sp_ts0); + fTPCTree->Branch("tpc_crt_sp_ts0_rwm_ref", "double", &_tpc_crt_sp_ts0_rwm_ref); + fTPCTree->Branch("tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref", "double", &_tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref); + fTPCTree->Branch("tpc_crt_sp_dts0", "double", &_tpc_crt_sp_dts0); + fTPCTree->Branch("tpc_crt_sp_ts1", "double", &_tpc_crt_sp_ts1); + fTPCTree->Branch("tpc_crt_sp_ts1_rwm_ref", "double", &_tpc_crt_sp_ts1_rwm_ref); + fTPCTree->Branch("tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref", "double", &_tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref); + fTPCTree->Branch("tpc_crt_sp_dts1", "double", &_tpc_crt_sp_dts1); +} + +void sbnd::crt::CRTTimingAnalysis::analyze(art::Event const& e) +{ + _run = e.id().run(); + _subrun = e.id().subRun(); + _event = e.id().event(); + + _crt_timing_reference_type = -1; + _crt_timing_reference_channel = -1; + + art::Handle TimingReferenceHandle; + e.getByLabel(fTimingReferenceModuleLabel, TimingReferenceHandle); + if(TimingReferenceHandle.isValid()) + { + _crt_timing_reference_type = TimingReferenceHandle->timingType; + _crt_timing_reference_channel = TimingReferenceHandle->timingChannel; + } + + // Get PTBs + art::Handle> PTBHandle; + e.getByLabel(fPTBModuleLabel, PTBHandle); + if(!PTBHandle.isValid()){ + std::cout << "PTB product " << fPTBModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + std::vector> PTBVec; + art::fill_ptr_vector(PTBVec, PTBHandle); + + // Fill PTB variables + AnalysePTBs(PTBVec); + + // Get TDCs + art::Handle> TDCHandle; + e.getByLabel(fTDCModuleLabel, TDCHandle); + if(!TDCHandle.isValid()){ + std::cout << "TDC product " << fTDCModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + std::vector> TDCVec; + art::fill_ptr_vector(TDCVec, TDCHandle); + + // Fill TDC variables + AnalyseTDCs(TDCVec); + + SortReferencing(); + + // Get CRTSpacePoints + art::Handle> CRTSpacePointHandle; + e.getByLabel(fCRTSpacePointModuleLabel, CRTSpacePointHandle); + if(!CRTSpacePointHandle.isValid()){ + std::cout << "CRTSpacePoint product " << fCRTSpacePointModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + std::vector> CRTSpacePointVec; + art::fill_ptr_vector(CRTSpacePointVec, CRTSpacePointHandle); + + // Get CRTSpacePoint to CRTCluster Assns + art::FindOneP spacepointsToClusters(CRTSpacePointHandle, e, fCRTSpacePointModuleLabel); + + // Get CRTClusters + art::Handle> CRTClusterHandle; + e.getByLabel(fCRTClusterModuleLabel, CRTClusterHandle); + if(!CRTClusterHandle.isValid()){ + std::cout << "CRTCluster product " << fCRTClusterModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + + // Get CRTCluster to CRTStripHit Assns + art::FindManyP clustersToStripHits(CRTClusterHandle, e, fCRTClusterModuleLabel); + + // Fill CRTSpacePoint variables + AnalyseCRTSpacePoints(CRTSpacePointVec, spacepointsToClusters, clustersToStripHits); + + // Get CRTTracks + art::Handle> CRTTrackHandle; + e.getByLabel(fCRTTrackModuleLabel, CRTTrackHandle); + if(!CRTTrackHandle.isValid()){ + std::cout << "CRTTrack product " << fCRTTrackModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + std::vector> CRTTrackVec; + art::fill_ptr_vector(CRTTrackVec, CRTTrackHandle); + + // Get CRTTrack to CRTSpacePoint Assns + art::FindManyP tracksToSpacePoints(CRTTrackHandle, e, fCRTTrackModuleLabel); + + // Fill CRTTrack variables + AnalyseCRTTracks(CRTTrackVec, tracksToSpacePoints, spacepointsToClusters, clustersToStripHits); + + // Get TPCSlices + art::Handle> TPCSliceHandle; + e.getByLabel(fTPCSliceModuleLabel, TPCSliceHandle); + if(!TPCSliceHandle.isValid()){ + std::cout << "TPCSlice product " << fTPCSliceModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + std::vector> TPCSliceVec; + art::fill_ptr_vector(TPCSliceVec, TPCSliceHandle); + + // Get TPCSlice to CorrectedOpFlash Assns + art::FindManyP sliceToCorrectedOpFlashes(TPCSliceHandle, e, fCorrectedOpFlashModuleLabel); + + // Get TPCSlice to PFP Assns + art::FindManyP sliceToPFPs(TPCSliceHandle, e, fTPCSliceModuleLabel); + + // Get TPCPFPs + art::Handle> TPCPFPHandle; + e.getByLabel(fTPCSliceModuleLabel, TPCPFPHandle); + if(!TPCPFPHandle.isValid()){ + std::cout << "TPCPFP product " << fTPCSliceModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + + // Get PFP to Track Assns + art::FindOneP pfpToTrack(TPCPFPHandle, e, fTPCTrackModuleLabel); + + // Get TPCTracks + art::Handle> TPCTrackHandle; + e.getByLabel(fTPCTrackModuleLabel, TPCTrackHandle); + if(!TPCTrackHandle.isValid()){ + std::cout << "TPCTrack product " << fTPCTrackModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + + // Get Track to CRTSpacePoint Assns + art::FindOneP trackToCRTSpacePoint(TPCTrackHandle, e, fCRTSpacePointMatchingModuleLabel); + + AnalyseTPCSlices(TPCSliceVec, sliceToCorrectedOpFlashes, sliceToPFPs, pfpToTrack, trackToCRTSpacePoint, spacepointsToClusters, clustersToStripHits); +} + +void sbnd::crt::CRTTimingAnalysis::AnalysePTBs(std::vector> &PTBVec) +{ + unsigned nHLTs = 0; + + for(auto const& ptb : PTBVec) + nHLTs += ptb->GetNHLTriggers(); + + _ptb_hlt_trigger.resize(nHLTs); + _ptb_hlt_timestamp.resize(nHLTs); + + unsigned hlt_i = 0; + + for(auto const& ptb : PTBVec) + { + for(unsigned i = 0; i < ptb->GetNHLTriggers(); ++i) + { + _ptb_hlt_trigger[hlt_i] = ptb->GetHLTrigger(i).trigger_word; + _ptb_hlt_timestamp[hlt_i] = ptb->GetHLTrigger(i).timestamp * 20; + + ++hlt_i; + } + } + + unsigned nLLTs = 0; + + for(auto const& ptb : PTBVec) + nLLTs += ptb->GetNLLTriggers(); + + _ptb_llt_trigger.resize(nLLTs); + _ptb_llt_timestamp.resize(nLLTs); + + unsigned llt_i = 0; + + for(auto const& ptb : PTBVec) + { + for(unsigned i = 0; i < ptb->GetNLLTriggers(); ++i) + { + _ptb_llt_trigger[llt_i] = ptb->GetLLTrigger(i).trigger_word; + _ptb_llt_timestamp[llt_i] = ptb->GetLLTrigger(i).timestamp * 20; + + ++llt_i; + } + } +} + +void sbnd::crt::CRTTimingAnalysis::AnalyseTDCs(std::vector> &TDCVec) +{ + const unsigned nTDCs = TDCVec.size(); + + _tdc_channel.resize(nTDCs); + _tdc_timestamp.resize(nTDCs); + _tdc_offset.resize(nTDCs); + _tdc_name.resize(nTDCs); + + unsigned tdc_i = 0; + + for(auto const& tdc : TDCVec) + { + _tdc_channel[tdc_i] = tdc->Channel(); + _tdc_timestamp[tdc_i] = tdc->Timestamp(); + _tdc_offset[tdc_i] = tdc->Offset(); + _tdc_name[tdc_i] = tdc->Name(); + + ++tdc_i; + } +} + +void sbnd::crt::CRTTimingAnalysis::SortReferencing() +{ + _etrig_good = false; _rwm_good = false; _ptb_hlt_beam_gate_good = false; _crt_t1_reset_good = false; + _rwm_etrig_diff = std::numeric_limits::max(); _ptb_hlt_beam_gate_etrig_diff = std::numeric_limits::max(); + _rwm_crt_t1_reset_diff = std::numeric_limits::max(); _ptb_hlt_beam_gate_crt_t1_reset_diff = std::numeric_limits::max(); + _rwm_ptb_hlt_beam_gate_diff = std::numeric_limits::max(); + + int etrig_count = 0, etrig_id = -1, rwm_count = 0, rwm_id = -1, crt_t1_reset_count = 0, crt_t1_reset_id = -1; + + for(unsigned int tdc_i = 0; tdc_i < _tdc_channel.size(); ++tdc_i) + { + if(_tdc_channel[tdc_i] == 4) + { + ++etrig_count; + etrig_id = tdc_i; + } + else if(_tdc_channel[tdc_i] == 2) + { + ++rwm_count; + rwm_id = tdc_i; + } + else if(_tdc_channel[tdc_i] == 0) + { + ++crt_t1_reset_count; + crt_t1_reset_id = tdc_i; + } + } + + uint64_t etrig = std::numeric_limits::max(), rwm = std::numeric_limits::max(), + hlt = std::numeric_limits::max(), crt_t1_reset = std::numeric_limits::max(); + + if(etrig_count == 1) + { + _etrig_good = true; + etrig = _tdc_timestamp[etrig_id]; + } + + if(rwm_count == 1) + { + _rwm_good = true; + rwm = _tdc_timestamp[rwm_id]; + } + + if(etrig_count == 1) + { + double closest_diff = std::numeric_limits::max(); + + for(unsigned int ptb_i = 0; ptb_i < _ptb_hlt_trigger.size(); ++ptb_i) + { + std::bitset<32> hlt_bitmask = std::bitset<32>(_ptb_hlt_trigger[ptb_i]); + + for(uint32_t allowed_hlt : fAllowedPTBHLTs) + { + if(hlt_bitmask[allowed_hlt]) + { + _ptb_hlt_beam_gate_good = true; + + uint64_t temp_hlt = _ptb_hlt_timestamp[ptb_i]; + double diff = etrig > temp_hlt ? etrig - temp_hlt : -1. * (temp_hlt - etrig); + + if(std::abs(diff) < closest_diff) + { + closest_diff = diff; + hlt = temp_hlt; + } + } + } + } + } + + if(crt_t1_reset_count == 1) + { + _crt_t1_reset_good = true; + crt_t1_reset = _tdc_timestamp[crt_t1_reset_id]; + } + + if(_etrig_good && _rwm_good) + _rwm_etrig_diff = etrig > rwm ? etrig - rwm : -1. * (rwm - etrig); + + if(_etrig_good && _ptb_hlt_beam_gate_good) + _ptb_hlt_beam_gate_etrig_diff = etrig > hlt ? etrig - hlt : -1. * (hlt - etrig); + + if(_crt_t1_reset_good && _rwm_good) + _rwm_crt_t1_reset_diff = crt_t1_reset > rwm ? crt_t1_reset - rwm : -1. * (rwm - crt_t1_reset); + + if(_etrig_good && _crt_t1_reset_good && _ptb_hlt_beam_gate_good) + _ptb_hlt_beam_gate_crt_t1_reset_diff = crt_t1_reset > hlt ? crt_t1_reset - hlt : -1. * (hlt - crt_t1_reset); + + if(_etrig_good && _rwm_good && _ptb_hlt_beam_gate_good) + _rwm_ptb_hlt_beam_gate_diff = hlt > rwm ? hlt - rwm : -1. * (rwm - hlt); +} + +void sbnd::crt::CRTTimingAnalysis::AnalyseCRTSpacePoints(const std::vector> &CRTSpacePointVec, + const art::FindOneP &spacepointsToClusters, + const art::FindManyP &clustersToStripHits) +{ +} + +void sbnd::crt::CRTTimingAnalysis::AnalyseCRTTracks(const std::vector> &CRTTrackVec, + const art::FindManyP &tracksToSpacePoints, + const art::FindOneP &spacepointsToClusters, + const art::FindManyP &clustersToStripHits) +{ +} + +void sbnd::crt::CRTTimingAnalysis::AnalyseTPCSlices(const std::vector> &TPCSliceVec, + const art::FindManyP &sliceToCorrectedOpFlashes, + const art::FindManyP &sliceToPFPs, + const art::FindOneP &pfpToTrack, + const art::FindOneP &trackToCRTSpacePoint, + const art::FindOneP &spacepointsToClusters, + const art::FindManyP &clustersToStripHits) +{ +} + +DEFINE_ART_MODULE(sbnd::crt::CRTTimingAnalysis) diff --git a/sbndcode/CRT/CRTAna/crttimingana_sbnd.fcl b/sbndcode/CRT/CRTAna/crttimingana_sbnd.fcl new file mode 100644 index 000000000..4a9bff36a --- /dev/null +++ b/sbndcode/CRT/CRTAna/crttimingana_sbnd.fcl @@ -0,0 +1,19 @@ +BEGIN_PROLOG + +crttophatana_data_sbnd: +{ + module_type: "CRTTimingAnalysis" + CRTClusterModuleLabel: "crtclustering" + CRTSpacePointModuleLabel: "crtspacepoints" + CRTTrackModuleLabel: "crttracks" + PTBModuleLabel: "ptbdecoder" + TDCModuleLabel: "tdcdecoder" + TimingReferenceModuleLabel: "crtstrips" + TPCSliceModuleLabel: "pandoraSCE" + CorrectedOpFlashModuleLabel: "lightpropagationcorrectionSCE" + TPCTrackModuleLabel: "pandoraSCETrack" + CRTSpacePointMatchingModuleLabel: "crtspacepointmatchingSCE" + AllowedPTBHLTs: [ 26, 27 ] +} + +END_PROLOG From 46bb0a2a5136161c4d4e7577713fef732d0d195b Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Tue, 24 Feb 2026 11:04:27 -0600 Subject: [PATCH 13/31] Refactor cluster characterisation to allow external use of timing corrections --- .../CRTReco/CRTClusterCharacterisationAlg.cc | 31 ++++++++++++------- .../CRTReco/CRTClusterCharacterisationAlg.h | 6 +++- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/sbndcode/CRT/CRTReco/CRTClusterCharacterisationAlg.cc b/sbndcode/CRT/CRTReco/CRTClusterCharacterisationAlg.cc index 1b7e296cd..49c6dbb4c 100644 --- a/sbndcode/CRT/CRTReco/CRTClusterCharacterisationAlg.cc +++ b/sbndcode/CRT/CRTReco/CRTClusterCharacterisationAlg.cc @@ -198,14 +198,8 @@ namespace sbnd::crt { void CRTClusterCharacterisationAlg::CorrectTime(const art::Ptr &hit0, const art::Ptr &hit1, const geo::Point_t &pos, double &t0, double &et0, double &t1, double &et1) { - const double dist0 = fCRTGeoService->DistanceDownStrip(pos, hit0->Channel()); - const double dist1 = fCRTGeoService->DistanceDownStrip(pos, hit1->Channel()); - - const double pe0 = ReconstructPE(hit0, dist0); - const double pe1 = ReconstructPE(hit1, dist1); - - const double corr0 = TimingCorrectionOffset(dist0, pe0); - const double corr1 = TimingCorrectionOffset(dist1, pe1); + const double corr0 = TimingCorrectionOffset(hit0, pos); + const double corr1 = TimingCorrectionOffset(hit1, pos); t0 = (hit0->Ts0() - corr0 + hit1->Ts0() - corr1) / 2.; et0 = std::abs((hit0->Ts0() - corr0) - (hit1->Ts0() - corr1)) / 2.; @@ -214,14 +208,27 @@ namespace sbnd::crt { et1 = std::abs((hit0->Ts1() - corr0) - (hit1->Ts1() - corr1)) / 2.; } - double CRTClusterCharacterisationAlg::TimingCorrectionOffset(const double &dist, const double &pe) + double CRTClusterCharacterisationAlg::TimingCorrectionOffset(const art::Ptr &hit, const geo::Point_t &pos) { - - double t_TimeWalk = fTimeWalkNorm * std::exp(- fTimeWalkScale * pe); - double t_PropDelay = fPropDelay * dist; + double t_TimeWalk = TimeWalk(hit, pos); + double t_PropDelay = PropagationDelay(hit, pos); return t_PropDelay + t_TimeWalk; } + double CRTClusterCharacterisationAlg::TimeWalk(const art::Ptr &hit, const geo::Point_t &pos) + { + const double dist = fCRTGeoService->DistanceDownStrip(pos, hit->Channel()); + const double pe = ReconstructPE(hit, dist); + + return fTimeWalkNorm * std::exp(-fTimeWalkScale * pe); + } + + double CRTClusterCharacterisationAlg::PropagationDelay(const art::Ptr &hit, const geo::Point_t &pos) + { + const double dist = fCRTGeoService->DistanceDownStrip(pos, hit->Channel()); + return fPropDelay * dist; + } + void CRTClusterCharacterisationAlg::AggregatePositions(const std::vector &complete_spacepoints, geo::Point_t &pos, geo::Point_t &err) { double sum_x = 0., sum_y = 0., sum_z = 0.; diff --git a/sbndcode/CRT/CRTReco/CRTClusterCharacterisationAlg.h b/sbndcode/CRT/CRTReco/CRTClusterCharacterisationAlg.h index a622ef28d..373d47ed7 100644 --- a/sbndcode/CRT/CRTReco/CRTClusterCharacterisationAlg.h +++ b/sbndcode/CRT/CRTReco/CRTClusterCharacterisationAlg.h @@ -65,7 +65,11 @@ namespace sbnd::crt { void CorrectTime(const art::Ptr &hit0, const art::Ptr &hit1, const geo::Point_t &pos, double &t0, double &et0, double &t1, double &et1); - double TimingCorrectionOffset(const double &dist, const double &pe); + double TimingCorrectionOffset(const art::Ptr &hit, const geo::Point_t &pos); + + double TimeWalk(const art::Ptr &hit, const geo::Point_t &pos); + + double PropagationDelay(const art::Ptr &hit, const geo::Point_t &pos); void AggregatePositions(const std::vector &complete_spacepoints, geo::Point_t &pos, geo::Point_t &err); From 1459913bec4e7d241082900cad1ffa980ed0ca90 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Tue, 24 Feb 2026 11:10:31 -0600 Subject: [PATCH 14/31] Update channel map service to add timing chains --- .../ChannelMaps/CRT/CRTChannelMapService.h | 12 ++++ .../CRT/CRTChannelMapService_service.cc | 64 ++++++++++++++++--- .../CRT/SBNDCRTTimingChainMap_v1.txt | 20 ++++++ .../CRT/crt_channel_map_service_sbnd.fcl | 3 +- 4 files changed, 90 insertions(+), 9 deletions(-) create mode 100644 sbndcode/ChannelMaps/CRT/SBNDCRTTimingChainMap_v1.txt diff --git a/sbndcode/ChannelMaps/CRT/CRTChannelMapService.h b/sbndcode/ChannelMaps/CRT/CRTChannelMapService.h index fc22880d1..6fce72894 100644 --- a/sbndcode/ChannelMaps/CRT/CRTChannelMapService.h +++ b/sbndcode/ChannelMaps/CRT/CRTChannelMapService.h @@ -59,6 +59,12 @@ class SBND::CRTChannelMapService { unsigned int GetMAC5FromOfflineChannelID(const unsigned int offline_channel_id); + unsigned int GetTimingChainFromOfflineModuleID(unsigned int offline_module_id); + + unsigned int GetTimingChainFromOfflineChannelID(unsigned int offline_channel_id); + + unsigned int GetTimingChainFromMAC5(unsigned int mac5); + private: typedef struct ModuleInfo { @@ -75,6 +81,12 @@ class SBND::CRTChannelMapService { // look up channel info by MAC5 std::unordered_map fModuleInfoFromMAC5; ModuleInfo_t GetModuleInfoFromMAC5(unsigned int mac5) const; + + // look up timing chain by offline module number + std::unordered_map fTimingChainFromOfflineID; + + // look up channel info by MAC5 + std::unordered_map fTimingChainFromMAC5; }; DECLARE_ART_SERVICE(SBND::CRTChannelMapService, LEGACY) diff --git a/sbndcode/ChannelMaps/CRT/CRTChannelMapService_service.cc b/sbndcode/ChannelMaps/CRT/CRTChannelMapService_service.cc index 3e3d45cfa..63f27ad88 100644 --- a/sbndcode/ChannelMaps/CRT/CRTChannelMapService_service.cc +++ b/sbndcode/ChannelMaps/CRT/CRTChannelMapService_service.cc @@ -17,28 +17,30 @@ SBND::CRTChannelMapService::CRTChannelMapService(fhicl::ParameterSet const& pset) { - const std::string channelMapFile = pset.get("FileName"); + const std::string channelMapFile = pset.get("ChannelMapFileName"); + const std::string timingChainMapFile = pset.get("TimingChainMapFileName"); - std::string fullname; + std::string channelMapFileFullName, timingChainMapFileFullName; cet::search_path sp("FW_SEARCH_PATH"); - sp.find_file(channelMapFile, fullname); + sp.find_file(channelMapFile, channelMapFileFullName); + sp.find_file(timingChainMapFile, timingChainMapFileFullName); - if(fullname.empty()) + if(channelMapFileFullName.empty()) { std::cout << "SBND::CRTChannelMapService Input file " << channelMapFile << " not found" << std::endl; throw cet::exception("File not found"); } std::cout << "SBND CRT Channel Map: Building map from file " << channelMapFile << std::endl; - std::ifstream inFile(fullname, std::ios::in); + std::ifstream channelMapInFile(channelMapFileFullName, std::ios::in); std::string line; - while(std::getline(inFile,line)) + while(std::getline(channelMapInFile, line)) { std::stringstream linestream(line); SBND::CRTChannelMapService::ModuleInfo_t m; - linestream + linestream >> m.offline_module_id >> m.mac5 >> m.channel_order_swapped; @@ -49,7 +51,38 @@ SBND::CRTChannelMapService::CRTChannelMapService(fhicl::ParameterSet const& pset fModuleInfoFromMAC5[m.mac5] = m; } - inFile.close(); + channelMapInFile.close(); + + if(timingChainMapFileFullName.empty()) + { + std::cout << "SBND::CRTChannelMapService Input file " << timingChainMapFile << " not found" << std::endl; + throw cet::exception("File not found"); + } + + std::cout << "SBND CRT Channel Map: Building timing chain map from file " << timingChainMapFile << std::endl; + std::ifstream timingChainMapInFile(timingChainMapFileFullName, std::ios::in); + + while(std::getline(timingChainMapInFile, line)) + { + std::stringstream linestream(line); + + unsigned int timing_chain = std::numeric_limits::max(); + unsigned int n = 0; + + linestream + >> timing_chain + >> n; + + for(unsigned int i = 0; i < n; ++i) + { + unsigned int offline_module_id = std::numeric_limits::max(); + linestream >> offline_module_id; + fTimingChainFromOfflineID[offline_module_id] = timing_chain; + fTimingChainFromMAC5[GetMAC5FromOfflineModuleID(offline_module_id)] = timing_chain; + } + } + + timingChainMapInFile.close(); } SBND::CRTChannelMapService::ModuleInfo_t SBND::CRTChannelMapService::GetModuleInfoFromMAC5(unsigned int mac5) const @@ -202,4 +235,19 @@ unsigned int SBND::CRTChannelMapService::GetMAC5FromOfflineChannelID(const unsig return GetMAC5FromOfflineModuleID(GetOfflineModuleIDFromOfflineChannelID(offline_channel_id)); } +unsigned int SBND::CRTChannelMapService::GetTimingChainFromOfflineModuleID(unsigned int offline_module_id) +{ + return fTimingChainFromOfflineID[offline_module_id]; +} + +unsigned int SBND::CRTChannelMapService::GetTimingChainFromOfflineChannelID(unsigned int offline_channel_id) +{ + return GetTimingChainFromOfflineModuleID(GetOfflineModuleIDFromOfflineChannelID(offline_channel_id)); +} + +unsigned int SBND::CRTChannelMapService::GetTimingChainFromMAC5(unsigned int mac5) +{ + return fTimingChainFromMAC5[mac5]; +} + DEFINE_ART_SERVICE(SBND::CRTChannelMapService) diff --git a/sbndcode/ChannelMaps/CRT/SBNDCRTTimingChainMap_v1.txt b/sbndcode/ChannelMaps/CRT/SBNDCRTTimingChainMap_v1.txt new file mode 100644 index 000000000..e37aa53cb --- /dev/null +++ b/sbndcode/ChannelMaps/CRT/SBNDCRTTimingChainMap_v1.txt @@ -0,0 +1,20 @@ +0 8 127 126 125 124 123 122 120 121 +1 6 139 128 137 138 136 135 +2 6 134 133 132 131 130 129 +3 8 63 62 54 55 56 57 58 59 +4 8 64 65 50 51 52 53 61 60 +5 6 81 80 82 79 83 78 +6 6 66 67 68 69 77 76 +7 6 70 71 72 73 74 75 +8 9 115 106 107 108 109 110 111 112 113 +9 9 116 117 118 119 102 103 104 105 114 +10 9 101 84 85 86 87 96 95 94 93 +11 9 100 99 98 97 88 89 90 91 92 +12 6 33 32 31 30 40 41 +13 6 42 43 44 25 26 27 +14 7 37 38 39 29 28 49 48 +15 6 36 35 34 45 46 47 +16 6 21 22 23 24 9 8 +17 6 7 6 5 19 18 17 +18 7 12 11 10 15 16 0 1 +19 6 13 14 20 4 3 2 diff --git a/sbndcode/ChannelMaps/CRT/crt_channel_map_service_sbnd.fcl b/sbndcode/ChannelMaps/CRT/crt_channel_map_service_sbnd.fcl index a34f136cd..35945a2b4 100644 --- a/sbndcode/ChannelMaps/CRT/crt_channel_map_service_sbnd.fcl +++ b/sbndcode/ChannelMaps/CRT/crt_channel_map_service_sbnd.fcl @@ -2,7 +2,8 @@ BEGIN_PROLOG crt_channel_map_sbnd: { - FileName: "SBNDCRTChannelMap_Commissioning_v5.txt" + ChannelMapFileName: "SBNDCRTChannelMap_Commissioning_v5.txt" + TimingChainMapFileName: "SBNDCRTTimingChainMap_v1.txt" } END_PROLOG From 75870c2a5fb1d21a5e805874bb8382eb55d9f49e Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Tue, 24 Feb 2026 11:12:19 -0600 Subject: [PATCH 15/31] Fill space point branches in timing analysis --- sbndcode/CRT/CRTAna/CMakeLists.txt | 2 + .../CRT/CRTAna/CRTTimingAnalysis_module.cc | 154 +++++++++++++++++- 2 files changed, 153 insertions(+), 3 deletions(-) diff --git a/sbndcode/CRT/CRTAna/CMakeLists.txt b/sbndcode/CRT/CRTAna/CMakeLists.txt index 05de4d016..ad4284386 100644 --- a/sbndcode/CRT/CRTAna/CMakeLists.txt +++ b/sbndcode/CRT/CRTAna/CMakeLists.txt @@ -10,6 +10,8 @@ art_make( sbnobj::SBND_Timing sbnobj::Common_Reco sbndcode_CRT_CRTBackTracker + sbndcode_CRT_CRTReco + sbndcode_ChannelMaps_CRT_CRTChannelMapService_service ) install_fhicl() diff --git a/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc b/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc index 3fa9d0fd6..8b23a9699 100644 --- a/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc +++ b/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc @@ -35,6 +35,8 @@ #include "sbndcode/Geometry/GeometryWrappers/CRTGeoService.h" #include "sbndcode/Decoders/PTB/sbndptb.h" #include "sbndcode/Timing/SBNDRawTimingObj.h" +#include "sbndcode/Calibration/CRTDatabaseInterface/CRTCalibrationDatabase.h" +#include "sbndcode/CRT/CRTReco/CRTClusterCharacterisationAlg.h" namespace sbnd::crt { class CRTTimingAnalysis; @@ -65,6 +67,15 @@ class sbnd::crt::CRTTimingAnalysis : public art::EDAnalyzer { const art::FindOneP &spacepointsToClusters, const art::FindManyP &clustersToStripHits); + void ResetSPVariables(); + + void ResizeSPSHVecs(const unsigned n); + + double IntrinsicResolution(const std::vector &_sp_sh_channel_set, + const std::vector &_sp_sh_ts_set, + const std::vector &_sp_sh_time_walk_set, + const std::vector &_sp_sh_prop_delay_set); + void AnalyseCRTTracks(const std::vector> &CRTTrackVec, const art::FindManyP &tracksToSpacePoints, const art::FindOneP &spacepointsToClusters, @@ -80,7 +91,10 @@ class sbnd::crt::CRTTimingAnalysis : public art::EDAnalyzer { private: - art::ServiceHandle fCRTGeoService; + art::ServiceHandle fCRTGeoService; + art::ServiceHandle fCRTChannelMapService; + sbndDB::CRTCalibrationDatabase const *fCRTCalibrationDatabaseService; + CRTClusterCharacterisationAlg fCRTClusterCharacAlg; // fcl Controlled Variables std::string fCRTClusterModuleLabel, fCRTSpacePointModuleLabel, fCRTTrackModuleLabel, @@ -143,8 +157,9 @@ class sbnd::crt::CRTTimingAnalysis : public art::EDAnalyzer { std::vector _sp_sh_ts1_set; std::vector _sp_sh_time_walk_set; std::vector _sp_sh_prop_delay_set; - std::vector _sp_sh_cable_length_set; + std::vector _sp_sh_cable_length_ts0_set; std::vector _sp_sh_calib_offset_ts0_set; + std::vector _sp_sh_cable_length_ts1_set; std::vector _sp_sh_calib_offset_ts1_set; double _tr_start_x; @@ -204,6 +219,7 @@ class sbnd::crt::CRTTimingAnalysis : public art::EDAnalyzer { sbnd::crt::CRTTimingAnalysis::CRTTimingAnalysis(fhicl::ParameterSet const& p) : EDAnalyzer{p} + , fCRTClusterCharacAlg(p.get("CRTClusterCharacterisationAlg", fhicl::ParameterSet())) { fCRTClusterModuleLabel = p.get("CRTClusterModuleLabel"); fCRTSpacePointModuleLabel = p.get("CRTSpacePointModuleLabel"); @@ -259,8 +275,9 @@ sbnd::crt::CRTTimingAnalysis::CRTTimingAnalysis(fhicl::ParameterSet const& p) fSPTree->Branch("sp_sh_ts1_set", "std::vector", &_sp_sh_ts1_set); fSPTree->Branch("sp_sh_time_walk_set", "std::vector", &_sp_sh_time_walk_set); fSPTree->Branch("sp_sh_prop_delay_set", "std::vector", &_sp_sh_prop_delay_set); - fSPTree->Branch("sp_sh_cable_length_set", "std::vector", &_sp_sh_cable_length_set); + fSPTree->Branch("sp_sh_cable_length_ts0_set", "std::vector", &_sp_sh_cable_length_ts0_set); fSPTree->Branch("sp_sh_calib_offset_ts0_set", "std::vector", &_sp_sh_calib_offset_ts0_set); + fSPTree->Branch("sp_sh_cable_length_ts1_set", "std::vector", &_sp_sh_cable_length_ts1_set); fSPTree->Branch("sp_sh_calib_offset_ts1_set", "std::vector", &_sp_sh_calib_offset_ts1_set); fTrTree = fs->make("tracks",""); @@ -644,6 +661,137 @@ void sbnd::crt::CRTTimingAnalysis::AnalyseCRTSpacePoints(const std::vector &spacepointsToClusters, const art::FindManyP &clustersToStripHits) { + for(auto const& sp : CRTSpacePointVec) + { + ResetSPVariables(); + + const art::Ptr cl = spacepointsToClusters.at(sp.key()); + + const std::vector> shs = clustersToStripHits.at(cl.key()); + const unsigned n_shs = shs.size(); + ResizeSPSHVecs(n_shs); + + _sp_nhits = cl->NHits(); + _sp_tagger = cl->Tagger(); + _sp_x = sp->X(); + _sp_y = sp->Y(); + _sp_z = sp->Z(); + _sp_pe = sp->PE(); + _sp_ts0 = sp->Ts0(); + _sp_ts0_rwm_ref = _sp_ts0 + _rwm_etrig_diff; + _sp_ts0_ptb_hlt_beam_gate_ref = _sp_ts0 + _ptb_hlt_beam_gate_etrig_diff; + _sp_ts1 = sp->Ts1(); + _sp_ts1_rwm_ref = _sp_ts1 + _rwm_crt_t1_reset_diff; + _sp_ts1_ptb_hlt_beam_gate_ref = _sp_ts1 + _ptb_hlt_beam_gate_crt_t1_reset_diff; + + for(unsigned i = 0; i < n_shs; ++i) + { + const art::Ptr sh = shs[i]; + + _sp_sh_channel_set[i] = sh->Channel(); + _sp_sh_mac5_set[i] = fCRTChannelMapService->GetMAC5FromOfflineChannelID(_sp_sh_channel_set[i]); + _sp_sh_timing_chain_set[i] = fCRTChannelMapService->GetTimingChainFromOfflineChannelID(_sp_sh_channel_set[i]); + _sp_sh_ts0_set[i] = sh->Ts0(); + _sp_sh_ts1_set[i] = sh->Ts1(); + _sp_sh_time_walk_set[i] = fCRTClusterCharacAlg.TimeWalk(sh, {_sp_x, _sp_y, _sp_z}); + _sp_sh_prop_delay_set[i] = fCRTClusterCharacAlg.PropagationDelay(sh, {_sp_x, _sp_y, _sp_z}); + _sp_sh_cable_length_ts0_set[i] = fCRTCalibrationDatabaseService->getT0CableLengthOffset(_sp_sh_mac5_set[i]); + _sp_sh_calib_offset_ts0_set[i] = fCRTCalibrationDatabaseService->getT0CalibratedOffset(_sp_sh_mac5_set[i]); + _sp_sh_cable_length_ts1_set[i] = fCRTCalibrationDatabaseService->getT1CableLengthOffset(_sp_sh_mac5_set[i]); + _sp_sh_calib_offset_ts1_set[i] = fCRTCalibrationDatabaseService->getT1CalibratedOffset(_sp_sh_mac5_set[i]); + } + + _sp_dts0 = IntrinsicResolution(_sp_sh_channel_set, _sp_sh_ts0_set, _sp_sh_time_walk_set, _sp_sh_prop_delay_set); + _sp_dts1 = IntrinsicResolution(_sp_sh_channel_set, _sp_sh_ts1_set, _sp_sh_time_walk_set, _sp_sh_prop_delay_set); + + std::set timing_chain_set(_sp_sh_timing_chain_set.begin(), _sp_sh_timing_chain_set.end()); + _sp_single_timing_chain = timing_chain_set.size() == 1; + _sp_timing_chain = _sp_single_timing_chain ? *timing_chain_set.begin() : -1; + + fSPTree->Fill(); + } +} + +void sbnd::crt::CRTTimingAnalysis::ResetSPVariables() +{ + _sp_nhits = std::numeric_limits::max(); + + _sp_tagger = CRTTagger::kUndefinedTagger; + + _sp_x = std::numeric_limits::lowest(); + _sp_y = std::numeric_limits::lowest(); + _sp_z = std::numeric_limits::lowest(); + _sp_pe = std::numeric_limits::lowest(); + _sp_ts0 = std::numeric_limits::lowest(); + _sp_ts0_rwm_ref = std::numeric_limits::lowest(); + _sp_ts0_ptb_hlt_beam_gate_ref = std::numeric_limits::lowest(); + _sp_dts0 = std::numeric_limits::lowest(); + _sp_ts1 = std::numeric_limits::lowest(); + _sp_ts1_rwm_ref = std::numeric_limits::lowest(); + _sp_ts1_ptb_hlt_beam_gate_ref = std::numeric_limits::lowest(); + _sp_dts1 = std::numeric_limits::lowest(); + + _sp_single_timing_chain = false; + + _sp_timing_chain = std::numeric_limits::lowest(); + + _sp_sh_channel_set.clear(); + _sp_sh_mac5_set.clear(); + _sp_sh_timing_chain_set.clear(); + _sp_sh_ts0_set.clear(); + _sp_sh_ts1_set.clear(); + _sp_sh_time_walk_set.clear(); + _sp_sh_prop_delay_set.clear(); + _sp_sh_cable_length_ts0_set.clear(); + _sp_sh_calib_offset_ts0_set.clear(); + _sp_sh_cable_length_ts1_set.clear(); + _sp_sh_calib_offset_ts1_set.clear(); +} + +void sbnd::crt::CRTTimingAnalysis::ResizeSPSHVecs(const unsigned n) +{ + _sp_sh_channel_set.resize(n); + _sp_sh_mac5_set.resize(n); + _sp_sh_timing_chain_set.resize(n); + _sp_sh_ts0_set.resize(n); + _sp_sh_ts1_set.resize(n); + _sp_sh_time_walk_set.resize(n); + _sp_sh_prop_delay_set.resize(n); + _sp_sh_cable_length_ts0_set.resize(n); + _sp_sh_calib_offset_ts0_set.resize(n); + _sp_sh_cable_length_ts1_set.resize(n); + _sp_sh_calib_offset_ts1_set.resize(n); +} + +double sbnd::crt::CRTTimingAnalysis::IntrinsicResolution(const std::vector &_sp_sh_channel_set, + const std::vector &_sp_sh_ts_set, + const std::vector &_sp_sh_time_walk_set, + const std::vector &_sp_sh_prop_delay_set) +{ + struct SH { + int32_t channel; + double ts; + }; + + std::vector shs; + + for(unsigned i = 0; i < _sp_sh_channel_set.size(); ++i) + shs.push_back(SH({_sp_sh_channel_set[i], _sp_sh_ts_set[i] - _sp_sh_time_walk_set[i] - _sp_sh_prop_delay_set[i]})); + + std::sort(shs.begin(), shs.end(), [](auto &a, auto &b) + { return a.channel < b.channel; }); + + double sum = 0.; + + for(unsigned int i = 0; i < shs.size(); ++i) + { + for(unsigned int ii = i + 1; ii < shs.size(); ++ii) + sum += (shs[i].ts - shs[ii].ts); + } + + sum /= (shs.size() - 1); + + return sum; } void sbnd::crt::CRTTimingAnalysis::AnalyseCRTTracks(const std::vector> &CRTTrackVec, From 0f58321cb1ad6da6fc22f3de1c1ab63569c8b78c Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Wed, 25 Feb 2026 05:58:47 -0600 Subject: [PATCH 16/31] Add track content to CRTTimingAnalysis module, plus a few bugfixes to make run-able --- .../CRT/CRTAna/CRTTimingAnalysis_module.cc | 400 ++++++++++++------ 1 file changed, 273 insertions(+), 127 deletions(-) diff --git a/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc b/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc index 8b23a9699..482eb5d2d 100644 --- a/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc +++ b/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc @@ -40,6 +40,8 @@ namespace sbnd::crt { class CRTTimingAnalysis; + + constexpr double c = 3.3356e-2; // ns / cm } class sbnd::crt::CRTTimingAnalysis : public art::EDAnalyzer { @@ -57,6 +59,8 @@ class sbnd::crt::CRTTimingAnalysis : public art::EDAnalyzer { // Required functions. void analyze(art::Event const& e) override; + void ResetMaps(); + void AnalysePTBs(std::vector> &PTBVec); void AnalyseTDCs(std::vector> &TDCVec); @@ -77,10 +81,10 @@ class sbnd::crt::CRTTimingAnalysis : public art::EDAnalyzer { const std::vector &_sp_sh_prop_delay_set); void AnalyseCRTTracks(const std::vector> &CRTTrackVec, - const art::FindManyP &tracksToSpacePoints, - const art::FindOneP &spacepointsToClusters, - const art::FindManyP &clustersToStripHits); - + const art::FindManyP &tracksToSpacePoints); + + void ResetTrVariables(); + void AnalyseTPCSlices(const std::vector> &TPCSliceVec, const art::FindManyP &sliceToCorrectedOpFlashes, const art::FindManyP &sliceToPFPs, @@ -192,10 +196,12 @@ class sbnd::crt::CRTTimingAnalysis : public art::EDAnalyzer { int16_t _tr_tagger3; int16_t _tr_start_tagger; double _tr_start_dts0; + double _tr_start_dts1; bool _tr_start_single_timing_chain; int16_t _tr_start_timing_chain; int16_t _tr_end_tagger; double _tr_end_dts0; + double _tr_end_dts1; bool _tr_end_single_timing_chain; int16_t _tr_end_timing_chain; @@ -215,6 +221,12 @@ class sbnd::crt::CRTTimingAnalysis : public art::EDAnalyzer { double _tpc_crt_sp_ts1_rwm_ref; double _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref; double _tpc_crt_sp_dts1; + + // Maps + std::map fSPTaggerMap; + std::map fSPdTs0Map; + std::map fSPdTs1Map; + std::map fSPTimingChainMap; }; sbnd::crt::CRTTimingAnalysis::CRTTimingAnalysis(fhicl::ParameterSet const& p) @@ -233,41 +245,43 @@ sbnd::crt::CRTTimingAnalysis::CRTTimingAnalysis(fhicl::ParameterSet const& p) fCRTSpacePointMatchingModuleLabel = p.get("CRTSpacePointMatchingModuleLabel"); fAllowedPTBHLTs = p.get>("AllowedPTBHLTs"); + fCRTCalibrationDatabaseService = lar::providerFrom(); + art::ServiceHandle fs; fSPTree = fs->make("spacepoints",""); - fSPTree->Branch("run", "int", &_run); - fSPTree->Branch("subrun", "int", &_subrun); - fSPTree->Branch("event", "int", &_event); - fSPTree->Branch("crt_timing_reference_type", "int", &_crt_timing_reference_type); - fSPTree->Branch("crt_timing_reference_channel", "int", &_crt_timing_reference_channel); - - fSPTree->Branch("etrig_good", "bool", &_etrig_good); - fSPTree->Branch("rwm_good", "bool", &_rwm_good); - fSPTree->Branch("ptb_hlt_beam_gate_good", "bool", &_ptb_hlt_beam_gate_good); - fSPTree->Branch("crt_t1_reset_good", "bool", &_crt_t1_reset_good); - fSPTree->Branch("rwm_etrig_diff", "double", &_rwm_etrig_diff); - fSPTree->Branch("ptb_hlt_beam_gate_etrig_diff", "double", &_ptb_hlt_beam_gate_etrig_diff); - fSPTree->Branch("rwm_crt_t1_reset_diff", "double", &_rwm_crt_t1_reset_diff); - fSPTree->Branch("ptb_hlt_beam_gate_crt_t1_reset_diff", "double", &_ptb_hlt_beam_gate_crt_t1_reset_diff); - fSPTree->Branch("rwm_ptb_hlt_beam_gate_diff", "double", &_rwm_ptb_hlt_beam_gate_diff); - - fSPTree->Branch("sp_nhits", "uint16_t", &_sp_nhits); - fSPTree->Branch("sp_tagger", "int16_t", &_sp_tagger); - fSPTree->Branch("sp_x", "double", &_sp_x); - fSPTree->Branch("sp_y", "double", &_sp_y); - fSPTree->Branch("sp_z", "double", &_sp_z); - fSPTree->Branch("sp_pe", "double", &_sp_pe); - fSPTree->Branch("sp_ts0", "double", &_sp_ts0); - fSPTree->Branch("sp_ts0_rwm_ref", "double", &_sp_ts0_rwm_ref); - fSPTree->Branch("sp_ts0_ptb_hlt_beam_gate_ref", "double", &_sp_ts0_ptb_hlt_beam_gate_ref); - fSPTree->Branch("sp_dts0", "double", &_sp_dts0); - fSPTree->Branch("sp_ts1", "double", &_sp_ts1); - fSPTree->Branch("sp_ts1_rwm_ref", "double", &_sp_ts1_rwm_ref); - fSPTree->Branch("sp_ts1_ptb_hlt_beam_gate_ref", "double", &_sp_ts1_ptb_hlt_beam_gate_ref); - fSPTree->Branch("sp_dts1", "double", &_sp_dts1); - fSPTree->Branch("sp_single_timing_chain", "bool", &_sp_single_timing_chain); - fSPTree->Branch("sp_timing_chain", "int16_t", &_sp_timing_chain); + fSPTree->Branch("run", &_run); + fSPTree->Branch("subrun", &_subrun); + fSPTree->Branch("event", &_event); + fSPTree->Branch("crt_timing_reference_type", &_crt_timing_reference_type); + fSPTree->Branch("crt_timing_reference_channel", &_crt_timing_reference_channel); + + fSPTree->Branch("etrig_good", &_etrig_good); + fSPTree->Branch("rwm_good", &_rwm_good); + fSPTree->Branch("ptb_hlt_beam_gate_good", &_ptb_hlt_beam_gate_good); + fSPTree->Branch("crt_t1_reset_good", &_crt_t1_reset_good); + fSPTree->Branch("rwm_etrig_diff", &_rwm_etrig_diff); + fSPTree->Branch("ptb_hlt_beam_gate_etrig_diff", &_ptb_hlt_beam_gate_etrig_diff); + fSPTree->Branch("rwm_crt_t1_reset_diff", &_rwm_crt_t1_reset_diff); + fSPTree->Branch("ptb_hlt_beam_gate_crt_t1_reset_diff", &_ptb_hlt_beam_gate_crt_t1_reset_diff); + fSPTree->Branch("rwm_ptb_hlt_beam_gate_diff", &_rwm_ptb_hlt_beam_gate_diff); + + fSPTree->Branch("sp_nhits", &_sp_nhits); + fSPTree->Branch("sp_tagger", &_sp_tagger); + fSPTree->Branch("sp_x", &_sp_x); + fSPTree->Branch("sp_y", &_sp_y); + fSPTree->Branch("sp_z", &_sp_z); + fSPTree->Branch("sp_pe", &_sp_pe); + fSPTree->Branch("sp_ts0", &_sp_ts0); + fSPTree->Branch("sp_ts0_rwm_ref", &_sp_ts0_rwm_ref); + fSPTree->Branch("sp_ts0_ptb_hlt_beam_gate_ref", &_sp_ts0_ptb_hlt_beam_gate_ref); + fSPTree->Branch("sp_dts0", &_sp_dts0); + fSPTree->Branch("sp_ts1", &_sp_ts1); + fSPTree->Branch("sp_ts1_rwm_ref", &_sp_ts1_rwm_ref); + fSPTree->Branch("sp_ts1_ptb_hlt_beam_gate_ref", &_sp_ts1_ptb_hlt_beam_gate_ref); + fSPTree->Branch("sp_dts1", &_sp_dts1); + fSPTree->Branch("sp_single_timing_chain", &_sp_single_timing_chain); + fSPTree->Branch("sp_timing_chain", &_sp_timing_chain); fSPTree->Branch("sp_sh_channel_set", "std::vector", &_sp_sh_channel_set); fSPTree->Branch("sp_sh_mac5_set", "std::vector", &_sp_sh_mac5_set); fSPTree->Branch("sp_sh_timing_chain_set", "std::vector", &_sp_sh_timing_chain_set); @@ -281,96 +295,100 @@ sbnd::crt::CRTTimingAnalysis::CRTTimingAnalysis(fhicl::ParameterSet const& p) fSPTree->Branch("sp_sh_calib_offset_ts1_set", "std::vector", &_sp_sh_calib_offset_ts1_set); fTrTree = fs->make("tracks",""); - fTrTree->Branch("run", "int", &_run); - fTrTree->Branch("subrun", "int", &_subrun); - fTrTree->Branch("event", "int", &_event); - fTrTree->Branch("crt_timing_reference_type", "int", &_crt_timing_reference_type); - fTrTree->Branch("crt_timing_reference_channel", "int", &_crt_timing_reference_channel); - - fTrTree->Branch("etrig_good", "bool", &_etrig_good); - fTrTree->Branch("rwm_good", "bool", &_rwm_good); - fTrTree->Branch("ptb_hlt_beam_gate_good", "bool", &_ptb_hlt_beam_gate_good); - fTrTree->Branch("crt_t1_reset_good", "bool", &_crt_t1_reset_good); - fTrTree->Branch("rwm_etrig_diff", "double", &_rwm_etrig_diff); - fTrTree->Branch("ptb_hlt_beam_gate_etrig_diff", "double", &_ptb_hlt_beam_gate_etrig_diff); - fTrTree->Branch("rwm_crt_t1_reset_diff", "double", &_rwm_crt_t1_reset_diff); - fTrTree->Branch("ptb_hlt_beam_gate_crt_t1_reset_diff", "double", &_ptb_hlt_beam_gate_crt_t1_reset_diff); - fTrTree->Branch("rwm_ptb_hlt_beam_gate_diff", "double", &_rwm_ptb_hlt_beam_gate_diff); - - fTrTree->Branch("tr_start_x", "double", &_tr_start_x); - fTrTree->Branch("tr_start_y", "double", &_tr_start_y); - fTrTree->Branch("tr_start_z", "double", &_tr_start_z); - fTrTree->Branch("tr_end_x", "double", &_tr_end_x); - fTrTree->Branch("tr_end_y", "double", &_tr_end_y); - fTrTree->Branch("tr_end_z", "double", &_tr_end_z); - fTrTree->Branch("tr_dir_x", "double", &_tr_dir_x); - fTrTree->Branch("tr_dir_y", "double", &_tr_dir_y); - fTrTree->Branch("tr_dir_z", "double", &_tr_dir_z); - fTrTree->Branch("tr_ts0", "double", &_tr_ts0); - fTrTree->Branch("tr_ts0_rwm_ref", "double", &_tr_ts0_rwm_ref); - fTrTree->Branch("tr_ts0_ptb_hlt_beam_gate_ref", "double", &_tr_ts0_ptb_hlt_beam_gate_ref); - fTrTree->Branch("tr_ts1", "double", &_tr_ts1); - fTrTree->Branch("tr_ts1_rwm_ref", "double", &_tr_ts1_rwm_ref); - fTrTree->Branch("tr_ts1_ptb_hlt_beam_gate_ref", "double", &_tr_ts1_ptb_hlt_beam_gate_ref); - fTrTree->Branch("tr_pe", "double", &_tr_pe); - fTrTree->Branch("tr_length", "double", &_tr_length); - fTrTree->Branch("tr_length_tof", "double", &_tr_length_tof); - fTrTree->Branch("tr_tof_ts0", "double", &_tr_tof_ts0); - fTrTree->Branch("tr_tof_diff_ts0", "double", &_tr_tof_diff_ts0); - fTrTree->Branch("tr_tof_ts1", "double", &_tr_tof_ts1); - fTrTree->Branch("tr_tof_diff_ts1", "double", &_tr_tof_diff_ts1); - fTrTree->Branch("tr_theta", "double", &_tr_theta); - fTrTree->Branch("tr_phi", "double", &_tr_phi); - fTrTree->Branch("tr_triple", "bool", &_tr_triple); - fTrTree->Branch("tr_tagger1", "int16_t", &_tr_tagger1); - fTrTree->Branch("tr_tagger2", "int16_t", &_tr_tagger2); - fTrTree->Branch("tr_tagger3", "int16_t", &_tr_tagger3); - fTrTree->Branch("tr_start_tagger", "int16_t", &_tr_start_tagger); - fTrTree->Branch("tr_start_dts0", "double", &_tr_start_dts0); - fTrTree->Branch("tr_start_single_timing_chain", "bool", &_tr_start_single_timing_chain); - fTrTree->Branch("tr_start_timing_chain", "int16_t", &_tr_start_timing_chain); - fTrTree->Branch("tr_end_tagger", "int16_t", &_tr_end_tagger); - fTrTree->Branch("tr_end_dts0", "double", &_tr_end_dts0); - fTrTree->Branch("tr_end_single_timing_chain", "bool", &_tr_end_single_timing_chain); - fTrTree->Branch("tr_end_timing_chain", "int16_t", &_tr_end_timing_chain); + fTrTree->Branch("run", &_run); + fTrTree->Branch("subrun", &_subrun); + fTrTree->Branch("event", &_event); + fTrTree->Branch("crt_timing_reference_type", &_crt_timing_reference_type); + fTrTree->Branch("crt_timing_reference_channel", &_crt_timing_reference_channel); + + fTrTree->Branch("etrig_good", &_etrig_good); + fTrTree->Branch("rwm_good", &_rwm_good); + fTrTree->Branch("ptb_hlt_beam_gate_good", &_ptb_hlt_beam_gate_good); + fTrTree->Branch("crt_t1_reset_good", &_crt_t1_reset_good); + fTrTree->Branch("rwm_etrig_diff", &_rwm_etrig_diff); + fTrTree->Branch("ptb_hlt_beam_gate_etrig_diff", &_ptb_hlt_beam_gate_etrig_diff); + fTrTree->Branch("rwm_crt_t1_reset_diff", &_rwm_crt_t1_reset_diff); + fTrTree->Branch("ptb_hlt_beam_gate_crt_t1_reset_diff", &_ptb_hlt_beam_gate_crt_t1_reset_diff); + fTrTree->Branch("rwm_ptb_hlt_beam_gate_diff", &_rwm_ptb_hlt_beam_gate_diff); + + fTrTree->Branch("tr_start_x", &_tr_start_x); + fTrTree->Branch("tr_start_y", &_tr_start_y); + fTrTree->Branch("tr_start_z", &_tr_start_z); + fTrTree->Branch("tr_end_x", &_tr_end_x); + fTrTree->Branch("tr_end_y", &_tr_end_y); + fTrTree->Branch("tr_end_z", &_tr_end_z); + fTrTree->Branch("tr_dir_x", &_tr_dir_x); + fTrTree->Branch("tr_dir_y", &_tr_dir_y); + fTrTree->Branch("tr_dir_z", &_tr_dir_z); + fTrTree->Branch("tr_ts0", &_tr_ts0); + fTrTree->Branch("tr_ts0_rwm_ref", &_tr_ts0_rwm_ref); + fTrTree->Branch("tr_ts0_ptb_hlt_beam_gate_ref", &_tr_ts0_ptb_hlt_beam_gate_ref); + fTrTree->Branch("tr_ts1", &_tr_ts1); + fTrTree->Branch("tr_ts1_rwm_ref", &_tr_ts1_rwm_ref); + fTrTree->Branch("tr_ts1_ptb_hlt_beam_gate_ref", &_tr_ts1_ptb_hlt_beam_gate_ref); + fTrTree->Branch("tr_pe", &_tr_pe); + fTrTree->Branch("tr_length", &_tr_length); + fTrTree->Branch("tr_length_tof", &_tr_length_tof); + fTrTree->Branch("tr_tof_ts0", &_tr_tof_ts0); + fTrTree->Branch("tr_tof_diff_ts0", &_tr_tof_diff_ts0); + fTrTree->Branch("tr_tof_ts1", &_tr_tof_ts1); + fTrTree->Branch("tr_tof_diff_ts1", &_tr_tof_diff_ts1); + fTrTree->Branch("tr_theta", &_tr_theta); + fTrTree->Branch("tr_phi", &_tr_phi); + fTrTree->Branch("tr_triple", &_tr_triple); + fTrTree->Branch("tr_tagger1", &_tr_tagger1); + fTrTree->Branch("tr_tagger2", &_tr_tagger2); + fTrTree->Branch("tr_tagger3", &_tr_tagger3); + fTrTree->Branch("tr_start_tagger", &_tr_start_tagger); + fTrTree->Branch("tr_start_dts0", &_tr_start_dts0); + fTrTree->Branch("tr_start_dts1", &_tr_start_dts1); + fTrTree->Branch("tr_start_single_timing_chain", &_tr_start_single_timing_chain); + fTrTree->Branch("tr_start_timing_chain", &_tr_start_timing_chain); + fTrTree->Branch("tr_end_tagger", &_tr_end_tagger); + fTrTree->Branch("tr_end_dts0", &_tr_end_dts0); + fTrTree->Branch("tr_end_dts1", &_tr_end_dts1); + fTrTree->Branch("tr_end_single_timing_chain", &_tr_end_single_timing_chain); + fTrTree->Branch("tr_end_timing_chain", &_tr_end_timing_chain); fTPCTree = fs->make("slices",""); - fTPCTree->Branch("run", "int", &_run); - fTPCTree->Branch("subrun", "int", &_subrun); - fTPCTree->Branch("event", "int", &_event); - fTPCTree->Branch("crt_timing_reference_type", "int", &_crt_timing_reference_type); - fTPCTree->Branch("crt_timing_reference_channel", "int", &_crt_timing_reference_channel); - - fTPCTree->Branch("etrig_good", "bool", &_etrig_good); - fTPCTree->Branch("rwm_good", "bool", &_rwm_good); - fTPCTree->Branch("ptb_hlt_beam_gate_good", "bool", &_ptb_hlt_beam_gate_good); - fTPCTree->Branch("crt_t1_reset_good", "bool", &_crt_t1_reset_good); - fTPCTree->Branch("rwm_etrig_diff", "double", &_rwm_etrig_diff); - fTPCTree->Branch("ptb_hlt_beam_gate_etrig_diff", "double", &_ptb_hlt_beam_gate_etrig_diff); - fTPCTree->Branch("rwm_crt_t1_reset_diff", "double", &_rwm_crt_t1_reset_diff); - fTPCTree->Branch("ptb_hlt_beam_gate_crt_t1_reset_diff", "double", &_ptb_hlt_beam_gate_crt_t1_reset_diff); - fTPCTree->Branch("rwm_ptb_hlt_beam_gate_diff", "double", &_rwm_ptb_hlt_beam_gate_diff); - - fTPCTree->Branch("tpc_has_corrected_opflash", "bool", &_tpc_has_corrected_opflash); - fTPCTree->Branch("tpc_has_crt_sp_match", "bool", &_tpc_has_crt_sp_match); - fTPCTree->Branch("tpc_opflash_t0", "double", &_tpc_opflash_t0); - fTPCTree->Branch("tpc_opflash_nutof_light", "double", &_tpc_opflash_nutof_light); - fTPCTree->Branch("tpc_opflash_nutof_charge", "double", &_tpc_opflash_nutof_charge); - fTPCTree->Branch("tpc_opflash_t0_corrected", "double", &_tpc_opflash_t0_corrected); - fTPCTree->Branch("tpc_opflash_t0_corrected_rwm", "double", &_tpc_opflash_t0_corrected_rwm); - fTPCTree->Branch("tpc_crt_sp_score", "double", &_tpc_crt_sp_score); - fTPCTree->Branch("tpc_crt_sp_ts0", "double", &_tpc_crt_sp_ts0); - fTPCTree->Branch("tpc_crt_sp_ts0_rwm_ref", "double", &_tpc_crt_sp_ts0_rwm_ref); - fTPCTree->Branch("tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref", "double", &_tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref); - fTPCTree->Branch("tpc_crt_sp_dts0", "double", &_tpc_crt_sp_dts0); - fTPCTree->Branch("tpc_crt_sp_ts1", "double", &_tpc_crt_sp_ts1); - fTPCTree->Branch("tpc_crt_sp_ts1_rwm_ref", "double", &_tpc_crt_sp_ts1_rwm_ref); - fTPCTree->Branch("tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref", "double", &_tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref); - fTPCTree->Branch("tpc_crt_sp_dts1", "double", &_tpc_crt_sp_dts1); + fTPCTree->Branch("run", &_run); + fTPCTree->Branch("subrun", &_subrun); + fTPCTree->Branch("event", &_event); + fTPCTree->Branch("crt_timing_reference_type", &_crt_timing_reference_type); + fTPCTree->Branch("crt_timing_reference_channel", &_crt_timing_reference_channel); + + fTPCTree->Branch("etrig_good", &_etrig_good); + fTPCTree->Branch("rwm_good", &_rwm_good); + fTPCTree->Branch("ptb_hlt_beam_gate_good", &_ptb_hlt_beam_gate_good); + fTPCTree->Branch("crt_t1_reset_good", &_crt_t1_reset_good); + fTPCTree->Branch("rwm_etrig_diff", &_rwm_etrig_diff); + fTPCTree->Branch("ptb_hlt_beam_gate_etrig_diff", &_ptb_hlt_beam_gate_etrig_diff); + fTPCTree->Branch("rwm_crt_t1_reset_diff", &_rwm_crt_t1_reset_diff); + fTPCTree->Branch("ptb_hlt_beam_gate_crt_t1_reset_diff", &_ptb_hlt_beam_gate_crt_t1_reset_diff); + fTPCTree->Branch("rwm_ptb_hlt_beam_gate_diff", &_rwm_ptb_hlt_beam_gate_diff); + + fTPCTree->Branch("tpc_has_corrected_opflash", &_tpc_has_corrected_opflash); + fTPCTree->Branch("tpc_has_crt_sp_match", &_tpc_has_crt_sp_match); + fTPCTree->Branch("tpc_opflash_t0", &_tpc_opflash_t0); + fTPCTree->Branch("tpc_opflash_nutof_light", &_tpc_opflash_nutof_light); + fTPCTree->Branch("tpc_opflash_nutof_charge", &_tpc_opflash_nutof_charge); + fTPCTree->Branch("tpc_opflash_t0_corrected", &_tpc_opflash_t0_corrected); + fTPCTree->Branch("tpc_opflash_t0_corrected_rwm", &_tpc_opflash_t0_corrected_rwm); + fTPCTree->Branch("tpc_crt_sp_score", &_tpc_crt_sp_score); + fTPCTree->Branch("tpc_crt_sp_ts0", &_tpc_crt_sp_ts0); + fTPCTree->Branch("tpc_crt_sp_ts0_rwm_ref", &_tpc_crt_sp_ts0_rwm_ref); + fTPCTree->Branch("tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref", &_tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref); + fTPCTree->Branch("tpc_crt_sp_dts0", &_tpc_crt_sp_dts0); + fTPCTree->Branch("tpc_crt_sp_ts1", &_tpc_crt_sp_ts1); + fTPCTree->Branch("tpc_crt_sp_ts1_rwm_ref", &_tpc_crt_sp_ts1_rwm_ref); + fTPCTree->Branch("tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref", &_tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref); + fTPCTree->Branch("tpc_crt_sp_dts1", &_tpc_crt_sp_dts1); } void sbnd::crt::CRTTimingAnalysis::analyze(art::Event const& e) { + ResetMaps(); + _run = e.id().run(); _subrun = e.id().subRun(); _event = e.id().event(); @@ -455,7 +473,7 @@ void sbnd::crt::CRTTimingAnalysis::analyze(art::Event const& e) art::FindManyP tracksToSpacePoints(CRTTrackHandle, e, fCRTTrackModuleLabel); // Fill CRTTrack variables - AnalyseCRTTracks(CRTTrackVec, tracksToSpacePoints, spacepointsToClusters, clustersToStripHits); + AnalyseCRTTracks(CRTTrackVec, tracksToSpacePoints); // Get TPCSlices art::Handle> TPCSliceHandle; @@ -498,6 +516,14 @@ void sbnd::crt::CRTTimingAnalysis::analyze(art::Event const& e) AnalyseTPCSlices(TPCSliceVec, sliceToCorrectedOpFlashes, sliceToPFPs, pfpToTrack, trackToCRTSpacePoint, spacepointsToClusters, clustersToStripHits); } +void sbnd::crt::CRTTimingAnalysis::ResetMaps() +{ + fSPTaggerMap.clear(); + fSPdTs0Map.clear(); + fSPdTs1Map.clear(); + fSPTimingChainMap.clear(); +} + void sbnd::crt::CRTTimingAnalysis::AnalysePTBs(std::vector> &PTBVec) { unsigned nHLTs = 0; @@ -709,6 +735,11 @@ void sbnd::crt::CRTTimingAnalysis::AnalyseCRTSpacePoints(const std::vectorFill(); + + fSPTaggerMap[sp.key()] = _sp_tagger; + fSPdTs0Map[sp.key()] = _sp_dts0; + fSPdTs1Map[sp.key()] = _sp_dts1; + fSPTimingChainMap[sp.key()] = _sp_timing_chain; } } @@ -716,7 +747,8 @@ void sbnd::crt::CRTTimingAnalysis::ResetSPVariables() { _sp_nhits = std::numeric_limits::max(); - _sp_tagger = CRTTagger::kUndefinedTagger; + _sp_tagger = std::numeric_limits::lowest(); + _sp_timing_chain = std::numeric_limits::lowest(); _sp_x = std::numeric_limits::lowest(); _sp_y = std::numeric_limits::lowest(); @@ -733,8 +765,6 @@ void sbnd::crt::CRTTimingAnalysis::ResetSPVariables() _sp_single_timing_chain = false; - _sp_timing_chain = std::numeric_limits::lowest(); - _sp_sh_channel_set.clear(); _sp_sh_mac5_set.clear(); _sp_sh_timing_chain_set.clear(); @@ -795,10 +825,126 @@ double sbnd::crt::CRTTimingAnalysis::IntrinsicResolution(const std::vector> &CRTTrackVec, - const art::FindManyP &tracksToSpacePoints, - const art::FindOneP &spacepointsToClusters, - const art::FindManyP &clustersToStripHits) + const art::FindManyP &tracksToSpacePoints) +{ + for(auto const &tr : CRTTrackVec) + { + _tr_start_x = tr->Start().X(); + _tr_start_y = tr->Start().Y(); + _tr_start_z = tr->Start().Z(); + _tr_end_x = tr->End().X(); + _tr_end_y = tr->End().Y(); + _tr_end_z = tr->End().Z(); + _tr_dir_x = tr->Direction().X(); + _tr_dir_y = tr->Direction().Y(); + _tr_dir_z = tr->Direction().Z(); + _tr_ts0 = tr->Ts0(); + _tr_ts0_rwm_ref = _tr_ts0 + _rwm_etrig_diff; + _tr_ts0_ptb_hlt_beam_gate_ref = _tr_ts0 + _ptb_hlt_beam_gate_etrig_diff; + _tr_ts1 = tr->Ts1(); + _tr_ts1_rwm_ref = _tr_ts1 + _rwm_crt_t1_reset_diff; + _tr_ts1_ptb_hlt_beam_gate_ref = _tr_ts1 + _ptb_hlt_beam_gate_crt_t1_reset_diff; + _tr_pe = tr->PE(); + _tr_length = tr->Length(); + _tr_length_tof = _tr_length * c; + _tr_theta = tr->Theta(); + _tr_phi = tr->Phi(); + _tr_triple = tr->Triple(); + _tr_tagger1 = tr->Taggers()[0]; + _tr_tagger2 = tr->Taggers()[1]; + + if(_tr_triple) + _tr_tagger3 = tr->Taggers()[2]; + + std::vector> sps = tracksToSpacePoints.at(tr.key()); + std::sort(sps.begin(), sps.end(), [](auto &a, auto &b) + { return a->Ts0() < b->Ts0(); }); + + if((_tr_triple && sps.size() != 3) || (!_tr_triple && sps.size() != 2)) + { + const int expectation = _tr_triple ? 3 : 2; + std::cout << "CRTSpacePoint vector wrong size (" << sps.size() + << ") for track expectation (" << expectation << ")" << std::endl; + throw std::exception(); + } + + const art::Ptr start = sps[0]; + const art::Ptr end = _tr_triple ? sps[2] : sps[1]; + + _tr_tof_ts0 = end->Ts0() - start->Ts0(); + _tr_tof_diff_ts0 = _tr_tof_ts0 - _tr_length_tof; + _tr_tof_ts1 = end->Ts1() - start->Ts1(); + _tr_tof_diff_ts1 = _tr_tof_ts1 - _tr_length_tof; + _tr_start_tagger = fSPTaggerMap[start.key()]; + _tr_start_dts0 = fSPdTs0Map[start.key()]; + _tr_start_dts1 = fSPdTs1Map[start.key()]; + _tr_start_timing_chain = fSPTimingChainMap[start.key()]; + _tr_start_single_timing_chain = _tr_start_timing_chain != -1; + _tr_end_tagger = fSPTaggerMap[end.key()]; + _tr_end_dts0 = fSPdTs0Map[end.key()]; + _tr_end_dts1 = fSPdTs1Map[end.key()]; + _tr_end_timing_chain = fSPTimingChainMap[end.key()]; + _tr_end_single_timing_chain = _tr_end_timing_chain != -1; + + if(_tr_start_tagger != _tr_tagger1) + { + std::cout << "CRTTrack start tagger inconsistent between direct access (" << _tr_tagger1 + << ") and associated CRTSpacePoint (" << _tr_start_tagger << ")" << std::endl; + throw std::exception(); + } + + if((_tr_triple && _tr_end_tagger != _tr_tagger3) || (!_tr_triple && _tr_end_tagger != _tr_tagger2)) + { + const int expectation = _tr_triple ? _tr_tagger3 : _tr_tagger2; + std::cout << "CRTTrack end tagger inconsistent between direct access (" << expectation + << ") and associated CRTSpacePoint (" << _tr_end_tagger << ")" << std::endl; + throw std::exception(); + } + } +} + +void sbnd::crt::CRTTimingAnalysis::ResetTrVariables() { + _tr_start_x = std::numeric_limits::lowest(); + _tr_start_y = std::numeric_limits::lowest(); + _tr_start_z = std::numeric_limits::lowest(); + _tr_end_x = std::numeric_limits::lowest(); + _tr_end_y = std::numeric_limits::lowest(); + _tr_end_z = std::numeric_limits::lowest(); + _tr_dir_x = std::numeric_limits::lowest(); + _tr_dir_y = std::numeric_limits::lowest(); + _tr_dir_z = std::numeric_limits::lowest(); + _tr_ts0 = std::numeric_limits::lowest(); + _tr_ts0_rwm_ref = std::numeric_limits::lowest(); + _tr_ts0_ptb_hlt_beam_gate_ref = std::numeric_limits::lowest(); + _tr_ts1 = std::numeric_limits::lowest(); + _tr_ts1_rwm_ref = std::numeric_limits::lowest(); + _tr_ts1_ptb_hlt_beam_gate_ref = std::numeric_limits::lowest(); + _tr_pe = std::numeric_limits::lowest(); + _tr_length = std::numeric_limits::lowest(); + _tr_length_tof = std::numeric_limits::lowest(); + _tr_tof_ts0 = std::numeric_limits::lowest(); + _tr_tof_diff_ts0 = std::numeric_limits::lowest(); + _tr_tof_ts1 = std::numeric_limits::lowest(); + _tr_tof_diff_ts1 = std::numeric_limits::lowest(); + _tr_theta = std::numeric_limits::lowest(); + _tr_phi = std::numeric_limits::lowest(); + _tr_start_dts0 = std::numeric_limits::lowest(); + _tr_start_dts1 = std::numeric_limits::lowest(); + _tr_end_dts0 = std::numeric_limits::lowest(); + _tr_end_dts1 = std::numeric_limits::lowest(); + + _tr_triple = false; + _tr_start_single_timing_chain = false; + _tr_end_single_timing_chain = false; + + _tr_tagger1 = std::numeric_limits::lowest(); + _tr_tagger2 = std::numeric_limits::lowest(); + _tr_tagger3 = std::numeric_limits::lowest(); + _tr_start_tagger = std::numeric_limits::lowest(); + _tr_start_timing_chain = std::numeric_limits::lowest(); + _tr_end_tagger = std::numeric_limits::lowest(); + _tr_end_timing_chain = std::numeric_limits::lowest(); } void sbnd::crt::CRTTimingAnalysis::AnalyseTPCSlices(const std::vector> &TPCSliceVec, From 1ca6df619557c004581a6b631c88fdcfce169986 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Wed, 25 Feb 2026 05:59:50 -0600 Subject: [PATCH 17/31] Make fcl changes to run CRTTimingAnalysis --- sbndcode/CRT/CRTAna/crttimingana_sbnd.fcl | 5 +++- sbndcode/CRT/CRTAna/run_crttimingana_data.fcl | 28 +++++++++++++++++++ .../CRT/CRTReco/crtrecoproducers_sbnd.fcl | 5 +++- 3 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 sbndcode/CRT/CRTAna/run_crttimingana_data.fcl diff --git a/sbndcode/CRT/CRTAna/crttimingana_sbnd.fcl b/sbndcode/CRT/CRTAna/crttimingana_sbnd.fcl index 4a9bff36a..406e07264 100644 --- a/sbndcode/CRT/CRTAna/crttimingana_sbnd.fcl +++ b/sbndcode/CRT/CRTAna/crttimingana_sbnd.fcl @@ -1,6 +1,8 @@ +#include "crtrecoproducers_sbnd.fcl" + BEGIN_PROLOG -crttophatana_data_sbnd: +crttimingana_data_sbnd: { module_type: "CRTTimingAnalysis" CRTClusterModuleLabel: "crtclustering" @@ -14,6 +16,7 @@ crttophatana_data_sbnd: TPCTrackModuleLabel: "pandoraSCETrack" CRTSpacePointMatchingModuleLabel: "crtspacepointmatchingSCE" AllowedPTBHLTs: [ 26, 27 ] + CRTClusterCharacterisationAlg: @local::crtclustercharacterisationalg_data_sbnd } END_PROLOG diff --git a/sbndcode/CRT/CRTAna/run_crttimingana_data.fcl b/sbndcode/CRT/CRTAna/run_crttimingana_data.fcl new file mode 100644 index 000000000..bcdcfd52a --- /dev/null +++ b/sbndcode/CRT/CRTAna/run_crttimingana_data.fcl @@ -0,0 +1,28 @@ +#include "services_sbnd.fcl" +#include "crt_services_sbnd.fcl" +#include "crttimingana_sbnd.fcl" + +process_name: CRTTimingAna + +services: +{ + TFileService: { fileName: "crttimingana_sbnd.root" } + @table::sbnd_basic_services + @table::crt_services_data_sbnd +} + +source: +{ + module_type: RootInput +} + +physics: +{ + analyzers: + { + crttimingana: @local::crttimingana_data_sbnd + } + + ana: [ crttimingana ] + end_paths: [ ana ] +} diff --git a/sbndcode/CRT/CRTReco/crtrecoproducers_sbnd.fcl b/sbndcode/CRT/CRTReco/crtrecoproducers_sbnd.fcl index 0b4ca1c3c..cbfd1a765 100644 --- a/sbndcode/CRT/CRTReco/crtrecoproducers_sbnd.fcl +++ b/sbndcode/CRT/CRTReco/crtrecoproducers_sbnd.fcl @@ -54,6 +54,9 @@ crtclustercharacterisationalg_sbnd: TimeWalkScale: @local::sbnd_crtsim.DetSimParams.TDelayScale } +crtclustercharacterisationalg_data_sbnd: @local::crtclustercharacterisationalg_sbnd +crtclustercharacterisationalg_data_sbnd.TimeOffset: 0 + crtspacepointproducer_sbnd: { ClusterCharacterisationAlg: @local::crtclustercharacterisationalg_sbnd @@ -62,7 +65,7 @@ crtspacepointproducer_sbnd: } crtspacepointproducer_data_sbnd: @local::crtspacepointproducer_sbnd -crtspacepointproducer_data_sbnd.ClusterCharacterisationAlg.TimeOffset: 0 +crtspacepointproducer_data_sbnd.ClusterCharacterisationAlg: @local::crtclustercharacterisationalg_data_sbnd crttrackproducer_sbnd: { From 8f8b77b96957c868c88f89574991980af937a8ca Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Wed, 25 Feb 2026 06:00:12 -0600 Subject: [PATCH 18/31] Make sure timing chain map is installed to path --- sbndcode/ChannelMaps/CRT/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbndcode/ChannelMaps/CRT/CMakeLists.txt b/sbndcode/ChannelMaps/CRT/CMakeLists.txt index b67ef20a5..9e6a43cfa 100644 --- a/sbndcode/ChannelMaps/CRT/CMakeLists.txt +++ b/sbndcode/ChannelMaps/CRT/CMakeLists.txt @@ -2,7 +2,7 @@ install_headers() install_fhicl() install_source() -file(GLOB channel_map_file *ChannelMap*.txt) +file(GLOB channel_map_file *Map*.txt) install_fw( LIST ${channel_map_file} ) art_make(SERVICE_LIBRARIES From cacb8d84ef0969173ad11cfa043ec67f633d36ff Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Wed, 25 Feb 2026 08:30:23 -0600 Subject: [PATCH 19/31] Add TPC slice based variables --- .../CRT/CRTAna/CRTTimingAnalysis_module.cc | 98 ++++++++++++++++--- 1 file changed, 84 insertions(+), 14 deletions(-) diff --git a/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc b/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc index 482eb5d2d..bc2795de2 100644 --- a/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc +++ b/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc @@ -41,7 +41,8 @@ namespace sbnd::crt { class CRTTimingAnalysis; - constexpr double c = 3.3356e-2; // ns / cm + constexpr double fSpeedOfLightNanosecondPerCentimeter = 3.3356e-2; // ns / cm + constexpr double fMicrosecondToNanosecond = 1e3; // ns } class sbnd::crt::CRTTimingAnalysis : public art::EDAnalyzer { @@ -86,12 +87,12 @@ class sbnd::crt::CRTTimingAnalysis : public art::EDAnalyzer { void ResetTrVariables(); void AnalyseTPCSlices(const std::vector> &TPCSliceVec, - const art::FindManyP &sliceToCorrectedOpFlashes, + const art::FindOneP &sliceToCorrectedOpFlash, const art::FindManyP &sliceToPFPs, const art::FindOneP &pfpToTrack, - const art::FindOneP &trackToCRTSpacePoint, - const art::FindOneP &spacepointsToClusters, - const art::FindManyP &clustersToStripHits); + const art::FindOneP &trackToCRTSpacePoint); + + void ResetTPCVariables(); private: @@ -211,7 +212,8 @@ class sbnd::crt::CRTTimingAnalysis : public art::EDAnalyzer { double _tpc_opflash_nutof_light; double _tpc_opflash_nutof_charge; double _tpc_opflash_t0_corrected; - double _tpc_opflash_t0_corrected_rwm; + double _tpc_opflash_interaction_time_rwm; + double _tpc_opflash_front_face_rwm; double _tpc_crt_sp_score; double _tpc_crt_sp_ts0; double _tpc_crt_sp_ts0_rwm_ref; @@ -373,7 +375,8 @@ sbnd::crt::CRTTimingAnalysis::CRTTimingAnalysis(fhicl::ParameterSet const& p) fTPCTree->Branch("tpc_opflash_nutof_light", &_tpc_opflash_nutof_light); fTPCTree->Branch("tpc_opflash_nutof_charge", &_tpc_opflash_nutof_charge); fTPCTree->Branch("tpc_opflash_t0_corrected", &_tpc_opflash_t0_corrected); - fTPCTree->Branch("tpc_opflash_t0_corrected_rwm", &_tpc_opflash_t0_corrected_rwm); + fTPCTree->Branch("tpc_opflash_interaction_time_rwm", &_tpc_opflash_interaction_time_rwm); + fTPCTree->Branch("tpc_opflash_front_face_rwm", &_tpc_opflash_front_face_rwm); fTPCTree->Branch("tpc_crt_sp_score", &_tpc_crt_sp_score); fTPCTree->Branch("tpc_crt_sp_ts0", &_tpc_crt_sp_ts0); fTPCTree->Branch("tpc_crt_sp_ts0_rwm_ref", &_tpc_crt_sp_ts0_rwm_ref); @@ -486,7 +489,7 @@ void sbnd::crt::CRTTimingAnalysis::analyze(art::Event const& e) art::fill_ptr_vector(TPCSliceVec, TPCSliceHandle); // Get TPCSlice to CorrectedOpFlash Assns - art::FindManyP sliceToCorrectedOpFlashes(TPCSliceHandle, e, fCorrectedOpFlashModuleLabel); + art::FindOneP sliceToCorrectedOpFlash(TPCSliceHandle, e, fCorrectedOpFlashModuleLabel); // Get TPCSlice to PFP Assns art::FindManyP sliceToPFPs(TPCSliceHandle, e, fTPCSliceModuleLabel); @@ -513,7 +516,7 @@ void sbnd::crt::CRTTimingAnalysis::analyze(art::Event const& e) // Get Track to CRTSpacePoint Assns art::FindOneP trackToCRTSpacePoint(TPCTrackHandle, e, fCRTSpacePointMatchingModuleLabel); - AnalyseTPCSlices(TPCSliceVec, sliceToCorrectedOpFlashes, sliceToPFPs, pfpToTrack, trackToCRTSpacePoint, spacepointsToClusters, clustersToStripHits); + AnalyseTPCSlices(TPCSliceVec, sliceToCorrectedOpFlash, sliceToPFPs, pfpToTrack, trackToCRTSpacePoint); } void sbnd::crt::CRTTimingAnalysis::ResetMaps() @@ -829,6 +832,8 @@ void sbnd::crt::CRTTimingAnalysis::AnalyseCRTTracks(const std::vectorStart().X(); _tr_start_y = tr->Start().Y(); _tr_start_z = tr->Start().Z(); @@ -846,7 +851,7 @@ void sbnd::crt::CRTTimingAnalysis::AnalyseCRTTracks(const std::vectorPE(); _tr_length = tr->Length(); - _tr_length_tof = _tr_length * c; + _tr_length_tof = _tr_length * fSpeedOfLightNanosecondPerCentimeter; _tr_theta = tr->Theta(); _tr_phi = tr->Phi(); _tr_triple = tr->Triple(); @@ -900,6 +905,8 @@ void sbnd::crt::CRTTimingAnalysis::AnalyseCRTTracks(const std::vectorFill(); } } @@ -948,13 +955,76 @@ void sbnd::crt::CRTTimingAnalysis::ResetTrVariables() } void sbnd::crt::CRTTimingAnalysis::AnalyseTPCSlices(const std::vector> &TPCSliceVec, - const art::FindManyP &sliceToCorrectedOpFlashes, + const art::FindOneP &sliceToCorrectedOpFlash, const art::FindManyP &sliceToPFPs, const art::FindOneP &pfpToTrack, - const art::FindOneP &trackToCRTSpacePoint, - const art::FindOneP &spacepointsToClusters, - const art::FindManyP &clustersToStripHits) + const art::FindOneP &trackToCRTSpacePoint) +{ + for(auto const &sl : TPCSliceVec) + { + const art::Ptr copflash = sliceToCorrectedOpFlash.at(sl.key()); + + if(copflash.isNonnull()) + { + _tpc_has_corrected_opflash = true; + _tpc_opflash_t0 = copflash->OpFlashT0 * fMicrosecondToNanosecond; + _tpc_opflash_nutof_light = copflash->NuToFLight * fMicrosecondToNanosecond; + _tpc_opflash_nutof_charge = copflash->NuToFCharge * fMicrosecondToNanosecond; + _tpc_opflash_t0_corrected = copflash->OpFlashT0Corrected * fMicrosecondToNanosecond; + _tpc_opflash_interaction_time_rwm = _tpc_opflash_t0_corrected + 1738.; + _tpc_opflash_front_face_rwm = _tpc_opflash_interaction_time_rwm - _tpc_opflash_nutof_charge; + } + + const std::vector> pfps = sliceToPFPs.at(sl.key()); + + for(auto const &pfp : pfps) + { + const art::Ptr track = pfpToTrack.at(pfp.key()); + + if(track.isNonnull()) + { + const art::Ptr sp = trackToCRTSpacePoint.at(track.key()); + + if(sp.isNonnull()) + { + const anab::T0 spMatch = trackToCRTSpacePoint.data(track.key()).ref(); + + _tpc_has_crt_sp_match = true; + _tpc_crt_sp_score = spMatch.TriggerConfidence(); + _tpc_crt_sp_ts0 = sp->Ts0(); + _tpc_crt_sp_ts0_rwm_ref = _tpc_crt_sp_ts0 + _rwm_etrig_diff; + _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref = _tpc_crt_sp_ts0 + _ptb_hlt_beam_gate_etrig_diff; + _tpc_crt_sp_dts0 = fSPdTs0Map[sp.key()]; + _tpc_crt_sp_ts1 = sp->Ts1(); + _tpc_crt_sp_ts1_rwm_ref = _tpc_crt_sp_ts1 + _rwm_crt_t1_reset_diff; + _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref = _tpc_crt_sp_ts1 + _ptb_hlt_beam_gate_crt_t1_reset_diff; + _tpc_crt_sp_dts1 = fSPdTs1Map[sp.key()]; + } + } + } + } +} + +void sbnd::crt::CRTTimingAnalysis::ResetTPCVariables() { + _tpc_has_corrected_opflash = false; + _tpc_has_crt_sp_match = false; + + _tpc_opflash_t0 = std::numeric_limits::lowest(); + _tpc_opflash_nutof_light = std::numeric_limits::lowest(); + _tpc_opflash_nutof_charge = std::numeric_limits::lowest(); + _tpc_opflash_t0_corrected = std::numeric_limits::lowest(); + _tpc_opflash_interaction_time_rwm = std::numeric_limits::lowest(); + _tpc_opflash_front_face_rwm = std::numeric_limits::lowest(); + _tpc_crt_sp_score = std::numeric_limits::lowest(); + _tpc_crt_sp_ts0 = std::numeric_limits::lowest(); + _tpc_crt_sp_ts0_rwm_ref = std::numeric_limits::lowest(); + _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref = std::numeric_limits::lowest(); + _tpc_crt_sp_dts0 = std::numeric_limits::lowest(); + _tpc_crt_sp_ts1 = std::numeric_limits::lowest(); + _tpc_crt_sp_ts1_rwm_ref = std::numeric_limits::lowest(); + _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref = std::numeric_limits::lowest(); + _tpc_crt_sp_dts1 = std::numeric_limits::lowest(); } DEFINE_ART_MODULE(sbnd::crt::CRTTimingAnalysis) From 5e7f17d22faf8bfb328994a5c9455a2d12b1f487 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Wed, 25 Feb 2026 09:22:20 -0600 Subject: [PATCH 20/31] Add more reference shifts --- .../CRT/CRTAna/CRTTimingAnalysis_module.cc | 193 +++++++++++++----- 1 file changed, 143 insertions(+), 50 deletions(-) diff --git a/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc b/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc index bc2795de2..a1728c95d 100644 --- a/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc +++ b/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc @@ -144,14 +144,19 @@ class sbnd::crt::CRTTimingAnalysis : public art::EDAnalyzer { double _sp_x; double _sp_y; double _sp_z; + double _sp_front_face_adjustment; double _sp_pe; double _sp_ts0; double _sp_ts0_rwm_ref; double _sp_ts0_ptb_hlt_beam_gate_ref; + double _sp_ts0_rwm_ref_front_face; + double _sp_ts0_ptb_hlt_beam_gate_ref_front_face; double _sp_dts0; double _sp_ts1; double _sp_ts1_rwm_ref; double _sp_ts1_ptb_hlt_beam_gate_ref; + double _sp_ts1_rwm_ref_front_face; + double _sp_ts1_ptb_hlt_beam_gate_ref_front_face; double _sp_dts1; bool _sp_single_timing_chain; int16_t _sp_timing_chain; @@ -215,14 +220,26 @@ class sbnd::crt::CRTTimingAnalysis : public art::EDAnalyzer { double _tpc_opflash_interaction_time_rwm; double _tpc_opflash_front_face_rwm; double _tpc_crt_sp_score; + double _tpc_crt_sp_front_face_adjustment; + double _tpc_crt_sp_interaction_time_adjustment; double _tpc_crt_sp_ts0; double _tpc_crt_sp_ts0_rwm_ref; double _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref; + double _tpc_crt_sp_ts0_rwm_ref_front_face; + double _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref_front_face; + double _tpc_crt_sp_ts0_rwm_ref_interaction_time; + double _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref_interaction_time; double _tpc_crt_sp_dts0; double _tpc_crt_sp_ts1; double _tpc_crt_sp_ts1_rwm_ref; double _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref; + double _tpc_crt_sp_ts1_rwm_ref_front_face; + double _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref_front_face; + double _tpc_crt_sp_ts1_rwm_ref_interaction_time; + double _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref_interaction_time; double _tpc_crt_sp_dts1; + double _tpc_crt_ts0_pmt_diff; + double _tpc_crt_ts1_pmt_diff; // Maps std::map fSPTaggerMap; @@ -273,14 +290,19 @@ sbnd::crt::CRTTimingAnalysis::CRTTimingAnalysis(fhicl::ParameterSet const& p) fSPTree->Branch("sp_x", &_sp_x); fSPTree->Branch("sp_y", &_sp_y); fSPTree->Branch("sp_z", &_sp_z); + fSPTree->Branch("sp_front_face_adjustment", &_sp_front_face_adjustment); fSPTree->Branch("sp_pe", &_sp_pe); fSPTree->Branch("sp_ts0", &_sp_ts0); fSPTree->Branch("sp_ts0_rwm_ref", &_sp_ts0_rwm_ref); fSPTree->Branch("sp_ts0_ptb_hlt_beam_gate_ref", &_sp_ts0_ptb_hlt_beam_gate_ref); + fSPTree->Branch("sp_ts0_rwm_ref_front_face", &_sp_ts0_rwm_ref_front_face); + fSPTree->Branch("sp_ts0_ptb_hlt_beam_gate_ref_front_face", &_sp_ts0_ptb_hlt_beam_gate_ref_front_face); fSPTree->Branch("sp_dts0", &_sp_dts0); fSPTree->Branch("sp_ts1", &_sp_ts1); fSPTree->Branch("sp_ts1_rwm_ref", &_sp_ts1_rwm_ref); fSPTree->Branch("sp_ts1_ptb_hlt_beam_gate_ref", &_sp_ts1_ptb_hlt_beam_gate_ref); + fSPTree->Branch("sp_ts1_rwm_ref_front_face", &_sp_ts1_rwm_ref_front_face); + fSPTree->Branch("sp_ts1_ptb_hlt_beam_gate_ref_front_face", &_sp_ts1_ptb_hlt_beam_gate_ref_front_face); fSPTree->Branch("sp_dts1", &_sp_dts1); fSPTree->Branch("sp_single_timing_chain", &_sp_single_timing_chain); fSPTree->Branch("sp_timing_chain", &_sp_timing_chain); @@ -378,14 +400,26 @@ sbnd::crt::CRTTimingAnalysis::CRTTimingAnalysis(fhicl::ParameterSet const& p) fTPCTree->Branch("tpc_opflash_interaction_time_rwm", &_tpc_opflash_interaction_time_rwm); fTPCTree->Branch("tpc_opflash_front_face_rwm", &_tpc_opflash_front_face_rwm); fTPCTree->Branch("tpc_crt_sp_score", &_tpc_crt_sp_score); + fTPCTree->Branch("tpc_crt_sp_front_face_adjustment", &_tpc_crt_sp_front_face_adjustment); + fTPCTree->Branch("tpc_crt_sp_interaction_time_adjustment", &_tpc_crt_sp_interaction_time_adjustment); fTPCTree->Branch("tpc_crt_sp_ts0", &_tpc_crt_sp_ts0); fTPCTree->Branch("tpc_crt_sp_ts0_rwm_ref", &_tpc_crt_sp_ts0_rwm_ref); fTPCTree->Branch("tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref", &_tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref); + fTPCTree->Branch("tpc_crt_sp_ts0_rwm_ref_front_face", &_tpc_crt_sp_ts0_rwm_ref_front_face); + fTPCTree->Branch("tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref_front_face", &_tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref_front_face); + fTPCTree->Branch("tpc_crt_sp_ts0_rwm_ref_interaction_time", &_tpc_crt_sp_ts0_rwm_ref_interaction_time); + fTPCTree->Branch("tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref_interaction_time", &_tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref_interaction_time); fTPCTree->Branch("tpc_crt_sp_dts0", &_tpc_crt_sp_dts0); fTPCTree->Branch("tpc_crt_sp_ts1", &_tpc_crt_sp_ts1); fTPCTree->Branch("tpc_crt_sp_ts1_rwm_ref", &_tpc_crt_sp_ts1_rwm_ref); fTPCTree->Branch("tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref", &_tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref); + fTPCTree->Branch("tpc_crt_sp_ts1_rwm_ref_front_face", &_tpc_crt_sp_ts1_rwm_ref_front_face); + fTPCTree->Branch("tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref_front_face", &_tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref_front_face); + fTPCTree->Branch("tpc_crt_sp_ts1_rwm_ref_interaction_time", &_tpc_crt_sp_ts1_rwm_ref_interaction_time); + fTPCTree->Branch("tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref_interaction_time", &_tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref_interaction_time); fTPCTree->Branch("tpc_crt_sp_dts1", &_tpc_crt_sp_dts1); + fTPCTree->Branch("tpc_crt_ts0_pmt_diff", &_tpc_crt_ts0_pmt_diff); + fTPCTree->Branch("tpc_crt_ts1_pmt_diff", &_tpc_crt_ts1_pmt_diff); } void sbnd::crt::CRTTimingAnalysis::analyze(art::Event const& e) @@ -700,18 +734,23 @@ void sbnd::crt::CRTTimingAnalysis::AnalyseCRTSpacePoints(const std::vectorNHits(); - _sp_tagger = cl->Tagger(); - _sp_x = sp->X(); - _sp_y = sp->Y(); - _sp_z = sp->Z(); - _sp_pe = sp->PE(); - _sp_ts0 = sp->Ts0(); - _sp_ts0_rwm_ref = _sp_ts0 + _rwm_etrig_diff; - _sp_ts0_ptb_hlt_beam_gate_ref = _sp_ts0 + _ptb_hlt_beam_gate_etrig_diff; - _sp_ts1 = sp->Ts1(); - _sp_ts1_rwm_ref = _sp_ts1 + _rwm_crt_t1_reset_diff; - _sp_ts1_ptb_hlt_beam_gate_ref = _sp_ts1 + _ptb_hlt_beam_gate_crt_t1_reset_diff; + _sp_nhits = cl->NHits(); + _sp_tagger = cl->Tagger(); + _sp_x = sp->X(); + _sp_y = sp->Y(); + _sp_z = sp->Z(); + _sp_front_face_adjustment = _sp_z * fSpeedOfLightNanosecondPerCentimeter; + _sp_pe = sp->PE(); + _sp_ts0 = sp->Ts0(); + _sp_ts0_rwm_ref = _sp_ts0 + _rwm_etrig_diff; + _sp_ts0_ptb_hlt_beam_gate_ref = _sp_ts0 + _ptb_hlt_beam_gate_etrig_diff; + _sp_ts0_rwm_ref_front_face = _sp_ts0_rwm_ref - _sp_front_face_adjustment; + _sp_ts0_ptb_hlt_beam_gate_ref_front_face = _sp_ts0_ptb_hlt_beam_gate_ref - _sp_front_face_adjustment; + _sp_ts1 = sp->Ts1(); + _sp_ts1_rwm_ref = _sp_ts1 + _rwm_crt_t1_reset_diff; + _sp_ts1_ptb_hlt_beam_gate_ref = _sp_ts1 + _ptb_hlt_beam_gate_crt_t1_reset_diff; + _sp_ts1_rwm_ref_front_face = _sp_ts1_rwm_ref - _sp_front_face_adjustment; + _sp_ts1_ptb_hlt_beam_gate_ref_front_face = _sp_ts1_ptb_hlt_beam_gate_ref - _sp_front_face_adjustment; for(unsigned i = 0; i < n_shs; ++i) { @@ -753,18 +792,23 @@ void sbnd::crt::CRTTimingAnalysis::ResetSPVariables() _sp_tagger = std::numeric_limits::lowest(); _sp_timing_chain = std::numeric_limits::lowest(); - _sp_x = std::numeric_limits::lowest(); - _sp_y = std::numeric_limits::lowest(); - _sp_z = std::numeric_limits::lowest(); - _sp_pe = std::numeric_limits::lowest(); - _sp_ts0 = std::numeric_limits::lowest(); - _sp_ts0_rwm_ref = std::numeric_limits::lowest(); - _sp_ts0_ptb_hlt_beam_gate_ref = std::numeric_limits::lowest(); - _sp_dts0 = std::numeric_limits::lowest(); - _sp_ts1 = std::numeric_limits::lowest(); - _sp_ts1_rwm_ref = std::numeric_limits::lowest(); - _sp_ts1_ptb_hlt_beam_gate_ref = std::numeric_limits::lowest(); - _sp_dts1 = std::numeric_limits::lowest(); + _sp_x = std::numeric_limits::lowest(); + _sp_y = std::numeric_limits::lowest(); + _sp_z = std::numeric_limits::lowest(); + _sp_front_face_adjustment = std::numeric_limits::lowest(); + _sp_pe = std::numeric_limits::lowest(); + _sp_ts0 = std::numeric_limits::lowest(); + _sp_ts0_rwm_ref = std::numeric_limits::lowest(); + _sp_ts0_ptb_hlt_beam_gate_ref = std::numeric_limits::lowest(); + _sp_ts0_rwm_ref_front_face = std::numeric_limits::lowest(); + _sp_ts0_ptb_hlt_beam_gate_ref_front_face = std::numeric_limits::lowest(); + _sp_dts0 = std::numeric_limits::lowest(); + _sp_ts1 = std::numeric_limits::lowest(); + _sp_ts1_rwm_ref = std::numeric_limits::lowest(); + _sp_ts1_ptb_hlt_beam_gate_ref = std::numeric_limits::lowest(); + _sp_ts1_rwm_ref_front_face = std::numeric_limits::lowest(); + _sp_ts1_ptb_hlt_beam_gate_ref_front_face = std::numeric_limits::lowest(); + _sp_dts1 = std::numeric_limits::lowest(); _sp_single_timing_chain = false; @@ -962,6 +1006,8 @@ void sbnd::crt::CRTTimingAnalysis::AnalyseTPCSlices(const std::vector copflash = sliceToCorrectedOpFlash.at(sl.key()); if(copflash.isNonnull()) @@ -971,7 +1017,7 @@ void sbnd::crt::CRTTimingAnalysis::AnalyseTPCSlices(const std::vectorNuToFLight * fMicrosecondToNanosecond; _tpc_opflash_nutof_charge = copflash->NuToFCharge * fMicrosecondToNanosecond; _tpc_opflash_t0_corrected = copflash->OpFlashT0Corrected * fMicrosecondToNanosecond; - _tpc_opflash_interaction_time_rwm = _tpc_opflash_t0_corrected + 1738.; + _tpc_opflash_interaction_time_rwm = _tpc_opflash_t0_corrected; _tpc_opflash_front_face_rwm = _tpc_opflash_interaction_time_rwm - _tpc_opflash_nutof_charge; } @@ -989,19 +1035,54 @@ void sbnd::crt::CRTTimingAnalysis::AnalyseTPCSlices(const std::vectorTs0(); - _tpc_crt_sp_ts0_rwm_ref = _tpc_crt_sp_ts0 + _rwm_etrig_diff; - _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref = _tpc_crt_sp_ts0 + _ptb_hlt_beam_gate_etrig_diff; - _tpc_crt_sp_dts0 = fSPdTs0Map[sp.key()]; - _tpc_crt_sp_ts1 = sp->Ts1(); - _tpc_crt_sp_ts1_rwm_ref = _tpc_crt_sp_ts1 + _rwm_crt_t1_reset_diff; - _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref = _tpc_crt_sp_ts1 + _ptb_hlt_beam_gate_crt_t1_reset_diff; - _tpc_crt_sp_dts1 = fSPdTs1Map[sp.key()]; + const geo::Point_t track_start = track->Start(); + const geo::Point_t track_end = track->End(); + const geo::Point_t sp_pos = sp->Pos(); + + geo::Point_t interaction_point = (track_start - sp_pos).R() > (track_end - sp_pos).R() ? track_start : track_end; + const double dist = (interaction_point - sp_pos).R(); + + if(_tpc_has_crt_sp_match) + { + const double diff = _tpc_crt_sp_ts0_rwm_ref_interaction_time - _tpc_opflash_interaction_time_rwm - 120; + const double new_crt = sp->Ts0() + _rwm_etrig_diff - dist * fSpeedOfLightNanosecondPerCentimeter; + const double new_diff = new_crt - _tpc_opflash_interaction_time_rwm - 120; + + if(new_diff > diff) + continue; + } + + _tpc_has_crt_sp_match = true; + _tpc_crt_sp_score = spMatch.TriggerConfidence(); + _tpc_crt_sp_front_face_adjustment = sp_pos.Z() * fSpeedOfLightNanosecondPerCentimeter; + _tpc_crt_sp_interaction_time_adjustment = dist * fSpeedOfLightNanosecondPerCentimeter; + _tpc_crt_sp_ts0 = sp->Ts0(); + _tpc_crt_sp_ts0_rwm_ref = _tpc_crt_sp_ts0 + _rwm_etrig_diff; + _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref = _tpc_crt_sp_ts0 + _ptb_hlt_beam_gate_etrig_diff; + _tpc_crt_sp_ts0_rwm_ref_front_face = _tpc_crt_sp_ts0_rwm_ref - _tpc_crt_sp_front_face_adjustment; + _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref_front_face = _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref - _tpc_crt_sp_front_face_adjustment; + _tpc_crt_sp_ts0_rwm_ref_interaction_time = _tpc_crt_sp_ts0_rwm_ref - _tpc_crt_sp_interaction_time_adjustment; + _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref_interaction_time = _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref - _tpc_crt_sp_interaction_time_adjustment; + _tpc_crt_sp_dts0 = fSPdTs0Map[sp.key()]; + _tpc_crt_sp_ts1 = sp->Ts1(); + _tpc_crt_sp_ts1_rwm_ref = _tpc_crt_sp_ts1 + _rwm_crt_t1_reset_diff; + _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref = _tpc_crt_sp_ts1 + _ptb_hlt_beam_gate_crt_t1_reset_diff; + _tpc_crt_sp_ts1_rwm_ref_front_face = _tpc_crt_sp_ts1_rwm_ref - _tpc_crt_sp_front_face_adjustment; + _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref_front_face = _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref - _tpc_crt_sp_front_face_adjustment; + _tpc_crt_sp_ts1_rwm_ref_interaction_time = _tpc_crt_sp_ts1_rwm_ref - _tpc_crt_sp_interaction_time_adjustment; + _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref_interaction_time = _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref - _tpc_crt_sp_interaction_time_adjustment; + _tpc_crt_sp_dts1 = fSPdTs1Map[sp.key()]; } } } + + if(_tpc_has_corrected_opflash && _tpc_has_crt_sp_match) + { + _tpc_crt_ts0_pmt_diff = _tpc_crt_sp_ts0_rwm_ref_interaction_time - _tpc_opflash_interaction_time_rwm; + _tpc_crt_ts1_pmt_diff = _tpc_crt_sp_ts1_rwm_ref_interaction_time - _tpc_opflash_interaction_time_rwm; + } + + fTPCTree->Fill(); } } @@ -1010,21 +1091,33 @@ void sbnd::crt::CRTTimingAnalysis::ResetTPCVariables() _tpc_has_corrected_opflash = false; _tpc_has_crt_sp_match = false; - _tpc_opflash_t0 = std::numeric_limits::lowest(); - _tpc_opflash_nutof_light = std::numeric_limits::lowest(); - _tpc_opflash_nutof_charge = std::numeric_limits::lowest(); - _tpc_opflash_t0_corrected = std::numeric_limits::lowest(); - _tpc_opflash_interaction_time_rwm = std::numeric_limits::lowest(); - _tpc_opflash_front_face_rwm = std::numeric_limits::lowest(); - _tpc_crt_sp_score = std::numeric_limits::lowest(); - _tpc_crt_sp_ts0 = std::numeric_limits::lowest(); - _tpc_crt_sp_ts0_rwm_ref = std::numeric_limits::lowest(); - _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref = std::numeric_limits::lowest(); - _tpc_crt_sp_dts0 = std::numeric_limits::lowest(); - _tpc_crt_sp_ts1 = std::numeric_limits::lowest(); - _tpc_crt_sp_ts1_rwm_ref = std::numeric_limits::lowest(); - _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref = std::numeric_limits::lowest(); - _tpc_crt_sp_dts1 = std::numeric_limits::lowest(); + _tpc_opflash_t0 = std::numeric_limits::lowest(); + _tpc_opflash_nutof_light = std::numeric_limits::lowest(); + _tpc_opflash_nutof_charge = std::numeric_limits::lowest(); + _tpc_opflash_t0_corrected = std::numeric_limits::lowest(); + _tpc_opflash_interaction_time_rwm = std::numeric_limits::lowest(); + _tpc_opflash_front_face_rwm = std::numeric_limits::lowest(); + _tpc_crt_sp_score = std::numeric_limits::lowest(); + _tpc_crt_sp_front_face_adjustment = std::numeric_limits::lowest(); + _tpc_crt_sp_interaction_time_adjustment = std::numeric_limits::lowest(); + _tpc_crt_sp_ts0 = std::numeric_limits::lowest(); + _tpc_crt_sp_ts0_rwm_ref = std::numeric_limits::lowest(); + _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref = std::numeric_limits::lowest(); + _tpc_crt_sp_ts0_rwm_ref_front_face = std::numeric_limits::lowest(); + _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref_front_face = std::numeric_limits::lowest(); + _tpc_crt_sp_ts0_rwm_ref_interaction_time = std::numeric_limits::lowest(); + _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref_interaction_time = std::numeric_limits::lowest(); + _tpc_crt_sp_dts0 = std::numeric_limits::lowest(); + _tpc_crt_sp_ts1 = std::numeric_limits::lowest(); + _tpc_crt_sp_ts1_rwm_ref = std::numeric_limits::lowest(); + _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref = std::numeric_limits::lowest(); + _tpc_crt_sp_ts1_rwm_ref_front_face = std::numeric_limits::lowest(); + _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref_front_face = std::numeric_limits::lowest(); + _tpc_crt_sp_ts1_rwm_ref_interaction_time = std::numeric_limits::lowest(); + _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref_interaction_time = std::numeric_limits::lowest(); + _tpc_crt_sp_dts1 = std::numeric_limits::lowest(); + _tpc_crt_ts0_pmt_diff = std::numeric_limits::lowest(); + _tpc_crt_ts1_pmt_diff = std::numeric_limits::lowest(); } DEFINE_ART_MODULE(sbnd::crt::CRTTimingAnalysis) From 2b8362d60f3ee34413cfe927727b109e4bbc6651 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Thu, 26 Feb 2026 04:02:08 -0600 Subject: [PATCH 21/31] Add a few missing branches --- .../CRT/CRTAna/CRTTimingAnalysis_module.cc | 179 ++++++++++-------- 1 file changed, 105 insertions(+), 74 deletions(-) diff --git a/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc b/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc index a1728c95d..a1bdf11bb 100644 --- a/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc +++ b/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc @@ -172,80 +172,87 @@ class sbnd::crt::CRTTimingAnalysis : public art::EDAnalyzer { std::vector _sp_sh_cable_length_ts1_set; std::vector _sp_sh_calib_offset_ts1_set; - double _tr_start_x; - double _tr_start_y; - double _tr_start_z; - double _tr_end_x; - double _tr_end_y; - double _tr_end_z; - double _tr_dir_x; - double _tr_dir_y; - double _tr_dir_z; - double _tr_ts0; - double _tr_ts0_rwm_ref; - double _tr_ts0_ptb_hlt_beam_gate_ref; - double _tr_ts1; - double _tr_ts1_rwm_ref; - double _tr_ts1_ptb_hlt_beam_gate_ref; - double _tr_pe; - double _tr_length; - double _tr_length_tof; - double _tr_tof_ts0; - double _tr_tof_diff_ts0; - double _tr_tof_ts1; - double _tr_tof_diff_ts1; - double _tr_theta; - double _tr_phi; - bool _tr_triple; - int16_t _tr_tagger1; - int16_t _tr_tagger2; - int16_t _tr_tagger3; - int16_t _tr_start_tagger; - double _tr_start_dts0; - double _tr_start_dts1; - bool _tr_start_single_timing_chain; - int16_t _tr_start_timing_chain; - int16_t _tr_end_tagger; - double _tr_end_dts0; - double _tr_end_dts1; - bool _tr_end_single_timing_chain; - int16_t _tr_end_timing_chain; - - bool _tpc_has_corrected_opflash; - bool _tpc_has_crt_sp_match; - double _tpc_opflash_t0; - double _tpc_opflash_nutof_light; - double _tpc_opflash_nutof_charge; - double _tpc_opflash_t0_corrected; - double _tpc_opflash_interaction_time_rwm; - double _tpc_opflash_front_face_rwm; - double _tpc_crt_sp_score; - double _tpc_crt_sp_front_face_adjustment; - double _tpc_crt_sp_interaction_time_adjustment; - double _tpc_crt_sp_ts0; - double _tpc_crt_sp_ts0_rwm_ref; - double _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref; - double _tpc_crt_sp_ts0_rwm_ref_front_face; - double _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref_front_face; - double _tpc_crt_sp_ts0_rwm_ref_interaction_time; - double _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref_interaction_time; - double _tpc_crt_sp_dts0; - double _tpc_crt_sp_ts1; - double _tpc_crt_sp_ts1_rwm_ref; - double _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref; - double _tpc_crt_sp_ts1_rwm_ref_front_face; - double _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref_front_face; - double _tpc_crt_sp_ts1_rwm_ref_interaction_time; - double _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref_interaction_time; - double _tpc_crt_sp_dts1; - double _tpc_crt_ts0_pmt_diff; - double _tpc_crt_ts1_pmt_diff; + double _tr_start_x; + double _tr_start_y; + double _tr_start_z; + double _tr_end_x; + double _tr_end_y; + double _tr_end_z; + double _tr_dir_x; + double _tr_dir_y; + double _tr_dir_z; + double _tr_ts0; + double _tr_ts0_rwm_ref; + double _tr_ts0_ptb_hlt_beam_gate_ref; + double _tr_ts1; + double _tr_ts1_rwm_ref; + double _tr_ts1_ptb_hlt_beam_gate_ref; + double _tr_pe; + double _tr_length; + double _tr_length_tof; + double _tr_tof_ts0; + double _tr_tof_diff_ts0; + double _tr_tof_ts1; + double _tr_tof_diff_ts1; + double _tr_theta; + double _tr_phi; + bool _tr_triple; + int16_t _tr_tagger1; + int16_t _tr_tagger2; + int16_t _tr_tagger3; + int16_t _tr_start_tagger; + uint16_t _tr_start_nhits; + double _tr_start_dts0; + double _tr_start_dts1; + bool _tr_start_single_timing_chain; + int16_t _tr_start_timing_chain; + int16_t _tr_end_tagger; + uint16_t _tr_end_nhits; + double _tr_end_dts0; + double _tr_end_dts1; + bool _tr_end_single_timing_chain; + int16_t _tr_end_timing_chain; + + bool _tpc_has_corrected_opflash; + bool _tpc_has_crt_sp_match; + double _tpc_opflash_t0; + double _tpc_opflash_nutof_light; + double _tpc_opflash_nutof_charge; + double _tpc_opflash_t0_corrected; + double _tpc_opflash_interaction_time_rwm; + double _tpc_opflash_front_face_rwm; + double _tpc_crt_sp_score; + int16_t _tpc_crt_sp_tagger; + uint16_t _tpc_crt_sp_nhits; + bool _tpc_crt_sp_single_timing_chain; + int16_t _tpc_crt_sp_timing_chain; + double _tpc_crt_sp_front_face_adjustment; + double _tpc_crt_sp_interaction_time_adjustment; + double _tpc_crt_sp_ts0; + double _tpc_crt_sp_ts0_rwm_ref; + double _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref; + double _tpc_crt_sp_ts0_rwm_ref_front_face; + double _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref_front_face; + double _tpc_crt_sp_ts0_rwm_ref_interaction_time; + double _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref_interaction_time; + double _tpc_crt_sp_dts0; + double _tpc_crt_sp_ts1; + double _tpc_crt_sp_ts1_rwm_ref; + double _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref; + double _tpc_crt_sp_ts1_rwm_ref_front_face; + double _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref_front_face; + double _tpc_crt_sp_ts1_rwm_ref_interaction_time; + double _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref_interaction_time; + double _tpc_crt_sp_dts1; + double _tpc_crt_ts0_pmt_diff; + double _tpc_crt_ts1_pmt_diff; // Maps - std::map fSPTaggerMap; - std::map fSPdTs0Map; - std::map fSPdTs1Map; - std::map fSPTimingChainMap; + std::map fSPTaggerMap; + std::map fSPNHitsMap; + std::map fSPdTs0Map; + std::map fSPdTs1Map; + std::map fSPTimingChainMap; }; sbnd::crt::CRTTimingAnalysis::CRTTimingAnalysis(fhicl::ParameterSet const& p) @@ -364,11 +371,13 @@ sbnd::crt::CRTTimingAnalysis::CRTTimingAnalysis(fhicl::ParameterSet const& p) fTrTree->Branch("tr_tagger2", &_tr_tagger2); fTrTree->Branch("tr_tagger3", &_tr_tagger3); fTrTree->Branch("tr_start_tagger", &_tr_start_tagger); + fTrTree->Branch("tr_start_nhits", &_tr_start_nhits); fTrTree->Branch("tr_start_dts0", &_tr_start_dts0); fTrTree->Branch("tr_start_dts1", &_tr_start_dts1); fTrTree->Branch("tr_start_single_timing_chain", &_tr_start_single_timing_chain); fTrTree->Branch("tr_start_timing_chain", &_tr_start_timing_chain); fTrTree->Branch("tr_end_tagger", &_tr_end_tagger); + fTrTree->Branch("tr_end_nhits", &_tr_end_nhits); fTrTree->Branch("tr_end_dts0", &_tr_end_dts0); fTrTree->Branch("tr_end_dts1", &_tr_end_dts1); fTrTree->Branch("tr_end_single_timing_chain", &_tr_end_single_timing_chain); @@ -400,6 +409,10 @@ sbnd::crt::CRTTimingAnalysis::CRTTimingAnalysis(fhicl::ParameterSet const& p) fTPCTree->Branch("tpc_opflash_interaction_time_rwm", &_tpc_opflash_interaction_time_rwm); fTPCTree->Branch("tpc_opflash_front_face_rwm", &_tpc_opflash_front_face_rwm); fTPCTree->Branch("tpc_crt_sp_score", &_tpc_crt_sp_score); + fTPCTree->Branch("tpc_crt_sp_tagger", &_tpc_crt_sp_tagger); + fTPCTree->Branch("tpc_crt_sp_nhits", &_tpc_crt_sp_nhits); + fTPCTree->Branch("tpc_crt_sp_single_timing_chain", &_tpc_crt_sp_single_timing_chain); + fTPCTree->Branch("tpc_crt_sp_timing_chain", &_tpc_crt_sp_timing_chain); fTPCTree->Branch("tpc_crt_sp_front_face_adjustment", &_tpc_crt_sp_front_face_adjustment); fTPCTree->Branch("tpc_crt_sp_interaction_time_adjustment", &_tpc_crt_sp_interaction_time_adjustment); fTPCTree->Branch("tpc_crt_sp_ts0", &_tpc_crt_sp_ts0); @@ -556,6 +569,7 @@ void sbnd::crt::CRTTimingAnalysis::analyze(art::Event const& e) void sbnd::crt::CRTTimingAnalysis::ResetMaps() { fSPTaggerMap.clear(); + fSPNHitsMap.clear(); fSPdTs0Map.clear(); fSPdTs1Map.clear(); fSPTimingChainMap.clear(); @@ -779,6 +793,7 @@ void sbnd::crt::CRTTimingAnalysis::AnalyseCRTSpacePoints(const std::vectorFill(); fSPTaggerMap[sp.key()] = _sp_tagger; + fSPNHitsMap[sp.key()] = _sp_nhits; fSPdTs0Map[sp.key()] = _sp_dts0; fSPdTs1Map[sp.key()] = _sp_dts1; fSPTimingChainMap[sp.key()] = _sp_timing_chain; @@ -925,11 +940,13 @@ void sbnd::crt::CRTTimingAnalysis::AnalyseCRTTracks(const std::vectorTs1() - start->Ts1(); _tr_tof_diff_ts1 = _tr_tof_ts1 - _tr_length_tof; _tr_start_tagger = fSPTaggerMap[start.key()]; + _tr_start_nhits = fSPNHitsMap[start.key()]; _tr_start_dts0 = fSPdTs0Map[start.key()]; _tr_start_dts1 = fSPdTs1Map[start.key()]; _tr_start_timing_chain = fSPTimingChainMap[start.key()]; _tr_start_single_timing_chain = _tr_start_timing_chain != -1; _tr_end_tagger = fSPTaggerMap[end.key()]; + _tr_end_nhits = fSPNHitsMap[start.key()]; _tr_end_dts0 = fSPdTs0Map[end.key()]; _tr_end_dts1 = fSPdTs1Map[end.key()]; _tr_end_timing_chain = fSPTimingChainMap[end.key()]; @@ -996,6 +1013,10 @@ void sbnd::crt::CRTTimingAnalysis::ResetTrVariables() _tr_start_timing_chain = std::numeric_limits::lowest(); _tr_end_tagger = std::numeric_limits::lowest(); _tr_end_timing_chain = std::numeric_limits::lowest(); + + _tr_start_nhits = std::numeric_limits::lowest(); + _tr_end_nhits = std::numeric_limits::lowest(); + } void sbnd::crt::CRTTimingAnalysis::AnalyseTPCSlices(const std::vector> &TPCSliceVec, @@ -1054,6 +1075,10 @@ void sbnd::crt::CRTTimingAnalysis::AnalyseTPCSlices(const std::vectorTs0(); @@ -1088,8 +1113,9 @@ void sbnd::crt::CRTTimingAnalysis::AnalyseTPCSlices(const std::vector::lowest(); _tpc_opflash_nutof_light = std::numeric_limits::lowest(); @@ -1118,6 +1144,11 @@ void sbnd::crt::CRTTimingAnalysis::ResetTPCVariables() _tpc_crt_sp_dts1 = std::numeric_limits::lowest(); _tpc_crt_ts0_pmt_diff = std::numeric_limits::lowest(); _tpc_crt_ts1_pmt_diff = std::numeric_limits::lowest(); + + _tpc_crt_sp_tagger = std::numeric_limits::lowest(); + _tpc_crt_sp_timing_chain = std::numeric_limits::lowest(); + + _tpc_crt_sp_nhits = std::numeric_limits::lowest(); } DEFINE_ART_MODULE(sbnd::crt::CRTTimingAnalysis) From 7bc5dee871c6b1ea1dc6a4689cc405e50bdb2439 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Thu, 26 Feb 2026 04:11:49 -0600 Subject: [PATCH 22/31] More sensible default for uint --- sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc b/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc index a1bdf11bb..73846af9c 100644 --- a/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc +++ b/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc @@ -1014,8 +1014,8 @@ void sbnd::crt::CRTTimingAnalysis::ResetTrVariables() _tr_end_tagger = std::numeric_limits::lowest(); _tr_end_timing_chain = std::numeric_limits::lowest(); - _tr_start_nhits = std::numeric_limits::lowest(); - _tr_end_nhits = std::numeric_limits::lowest(); + _tr_start_nhits = std::numeric_limits::max(); + _tr_end_nhits = std::numeric_limits::max(); } @@ -1148,7 +1148,7 @@ void sbnd::crt::CRTTimingAnalysis::ResetTPCVariables() _tpc_crt_sp_tagger = std::numeric_limits::lowest(); _tpc_crt_sp_timing_chain = std::numeric_limits::lowest(); - _tpc_crt_sp_nhits = std::numeric_limits::lowest(); + _tpc_crt_sp_nhits = std::numeric_limits::max(); } DEFINE_ART_MODULE(sbnd::crt::CRTTimingAnalysis) From 44a0672f903903af59406a8ebc4be3f14abd71af Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Fri, 27 Feb 2026 04:54:01 -0600 Subject: [PATCH 23/31] Remove unnecessary tophat analysis module --- .../CRT/CRTAna/CRTTopHatAnalysis_module.cc | 821 ------------------ sbndcode/CRT/CRTAna/crttophatana_sbnd.fcl | 12 - sbndcode/CRT/CRTAna/run_crttophatana_data.fcl | 28 - 3 files changed, 861 deletions(-) delete mode 100644 sbndcode/CRT/CRTAna/CRTTopHatAnalysis_module.cc delete mode 100644 sbndcode/CRT/CRTAna/crttophatana_sbnd.fcl delete mode 100644 sbndcode/CRT/CRTAna/run_crttophatana_data.fcl diff --git a/sbndcode/CRT/CRTAna/CRTTopHatAnalysis_module.cc b/sbndcode/CRT/CRTAna/CRTTopHatAnalysis_module.cc deleted file mode 100644 index f338ce846..000000000 --- a/sbndcode/CRT/CRTAna/CRTTopHatAnalysis_module.cc +++ /dev/null @@ -1,821 +0,0 @@ -//////////////////////////////////////////////////////////////////////// -// Class: CRTTopHatAnalysis -// Plugin Type: analyzer -// File: CRTTopHatAnalysis_module.cc -// Author: Henry Lay (h.lay@sheffield.ac.uk) -//////////////////////////////////////////////////////////////////////// - -#include "art/Framework/Core/EDAnalyzer.h" -#include "art/Framework/Core/ModuleMacros.h" -#include "art/Framework/Principal/Event.h" -#include "art/Framework/Principal/Handle.h" -#include "art/Framework/Principal/Run.h" -#include "art/Framework/Principal/SubRun.h" -#include "canvas/Utilities/InputTag.h" -#include "fhiclcpp/ParameterSet.h" -#include "messagefacility/MessageLogger/MessageLogger.h" -#include "art_root_io/TFileService.h" -#include "canvas/Persistency/Common/FindManyP.h" - -#include "TTree.h" - -#include "lardataobj/AnalysisBase/T0.h" -#include "lardataobj/RecoBase/Track.h" -#include "lardataobj/RecoBase/PFParticle.h" -#include "lardataobj/RecoBase/PFParticleMetadata.h" - -#include "larsim/Utils/TruthMatchUtils.h" -#include "lardata/DetectorInfoServices/DetectorClocksService.h" - -#include "sbndaq-artdaq-core/Obj/SBND/pmtSoftwareTrigger.hh" - -#include "sbnobj/SBND/CRT/FEBData.hh" -#include "sbnobj/SBND/CRT/CRTStripHit.hh" -#include "sbnobj/SBND/CRT/CRTCluster.hh" -#include "sbnobj/SBND/CRT/CRTSpacePoint.hh" -#include "sbnobj/SBND/CRT/CRTTrack.hh" -#include "sbnobj/SBND/Timing/DAQTimestamp.hh" - -#include "sbndcode/Geometry/GeometryWrappers/CRTGeoService.h" -#include "sbndcode/Geometry/GeometryWrappers/TPCGeoAlg.h" -#include "sbndcode/CRT/CRTBackTracker/CRTBackTrackerAlg.h" -#include "sbndcode/CRT/CRTUtils/CRTCommonUtils.h" -#include "sbndcode/Decoders/PTB/sbndptb.h" -#include "sbndcode/Timing/SBNDRawTimingObj.h" - -namespace sbnd::crt { - class CRTTopHatAnalysis; -} - -class sbnd::crt::CRTTopHatAnalysis : public art::EDAnalyzer { -public: - explicit CRTTopHatAnalysis(fhicl::ParameterSet const& p); - // The compiler-generated destructor is fine for non-base - // classes without bare pointers or other resource use. - - // Plugins should not be copied or assigned. - CRTTopHatAnalysis(CRTTopHatAnalysis const&) = delete; - CRTTopHatAnalysis(CRTTopHatAnalysis&&) = delete; - CRTTopHatAnalysis& operator=(CRTTopHatAnalysis const&) = delete; - CRTTopHatAnalysis& operator=(CRTTopHatAnalysis&&) = delete; - - // Required functions. - void analyze(art::Event const& e) override; - - void AnalysePTBs(std::vector> &PTBVec); - - void AnalyseTDCs(std::vector> &TDCVec); - - void SortReferencing(); - - void AnalyseCRTStripHits(const art::Event &e, const std::vector> &CRTStripHitVec); - - void AnalyseCRTClusters(const art::Event &e, const std::vector> &CRTClusterVec, - const art::FindManyP &clustersToSpacePoints); - - void AnalyseCRTTracks(const art::Event &e, const std::vector> &CRTTrackVec); - - void AnalysePMTSoftwareTriggers(const art::Event &e, const std::vector> &PMTSoftwareTriggerVec); - - -private: - - art::ServiceHandle fCRTGeoService; - TPCGeoAlg fTPCGeoAlg; - - std::string fCRTStripHitModuleLabel, fCRTClusterModuleLabel, fCRTSpacePointModuleLabel, - fCRTTrackModuleLabel, fPTBModuleLabel, fTDCModuleLabel, fTimingReferenceModuleLabel, - fPMTSoftwareTriggerModuleLabel; - bool fDebug, fCutT0, fSavePMTSoftwareTrigger; - double fMinT0, fMaxT0; - std::vector fAllowedPTBHLTs; - - TTree* fTree; - - // Tree variables - - int _run; - int _subrun; - int _event; - int _crt_timing_reference_type; - int _crt_timing_reference_channel; - - //strip hit to select the strip which has ADC above threshold - std::vector _sh_channel; - std::vector _sh_tagger; - std::vector _sh_ts0; - std::vector _sh_ts0_rwm_ref; - std::vector _sh_ts0_ptb_hlt_beam_gate_ref; - std::vector _sh_ts1; - std::vector _sh_ts1_rwm_ref; - std::vector _sh_ts1_ptb_hlt_beam_gate_ref; - std::vector _sh_unixs; - std::vector _sh_pos; - std::vector _sh_err; - std::vector _sh_adc1; - std::vector _sh_adc2; - std::vector _sh_saturated1; - std::vector _sh_saturated2; - std::vector _sh_truth_trackid; - std::vector _sh_truth_completeness; - std::vector _sh_truth_purity; - std::vector _sh_truth_pos; - std::vector _sh_truth_energy; - std::vector _sh_truth_time; - - //cluster from x-y coincidence for CRTSpacePoint - std::vector _cl_ts0; - std::vector _cl_ts0_rwm_ref; - std::vector _cl_ts0_ptb_hlt_beam_gate_ref; - std::vector _cl_ts1; - std::vector _cl_ts1_rwm_ref; - std::vector _cl_ts1_ptb_hlt_beam_gate_ref; - std::vector _cl_unixs; - std::vector _cl_nhits; - std::vector _cl_tagger; - std::vector _cl_composition; - std::vector _cl_has_sp; - std::vector _cl_sp_x; - std::vector _cl_sp_ex; - std::vector _cl_sp_y; - std::vector _cl_sp_ey; - std::vector _cl_sp_z; - std::vector _cl_sp_ez; - std::vector _cl_sp_pe; - std::vector _cl_sp_ts0; - std::vector _cl_sp_ts0_rwm_ref; - std::vector _cl_sp_ts0_ptb_hlt_beam_gate_ref; - std::vector _cl_sp_ets0; - std::vector _cl_sp_ts1; - std::vector _cl_sp_ts1_rwm_ref; - std::vector _cl_sp_ts1_ptb_hlt_beam_gate_ref; - std::vector _cl_sp_ets1; - std::vector _cl_sp_complete; - - //track level information - std::vector _tr_start_x; - std::vector _tr_start_y; - std::vector _tr_start_z; - std::vector _tr_end_x; - std::vector _tr_end_y; - std::vector _tr_end_z; - std::vector _tr_dir_x; - std::vector _tr_dir_y; - std::vector _tr_dir_z; - std::vector _tr_ts0; - std::vector _tr_ts0_rwm_ref; - std::vector _tr_ts0_ptb_hlt_beam_gate_ref; - std::vector _tr_ets0; - std::vector _tr_ts1; - std::vector _tr_ts1_rwm_ref; - std::vector _tr_ts1_ptb_hlt_beam_gate_ref; - std::vector _tr_ets1; - std::vector _tr_pe; - std::vector _tr_length; - std::vector _tr_tof; - std::vector _tr_theta; - std::vector _tr_phi; - std::vector _tr_triple; - std::vector _tr_tagger1; - std::vector _tr_tagger2; - std::vector _tr_tagger3; - - std::vector _ptb_hlt_trigger; - std::vector _ptb_hlt_timestamp; - - std::vector _ptb_llt_trigger; - std::vector _ptb_llt_timestamp; - - std::vector _tdc_channel; - std::vector _tdc_timestamp; - std::vector _tdc_offset; - std::vector _tdc_name; - - bool _etrig_good, _rwm_good, _ptb_hlt_beam_gate_good, _crt_t1_reset_good; - double _rwm_etrig_diff, _ptb_hlt_beam_gate_etrig_diff, _rwm_crt_t1_reset_diff, _ptb_hlt_beam_gate_crt_t1_reset_diff, - _rwm_ptb_hlt_beam_gate_diff; - - bool _pmt_st_found_trigger; - double _pmt_st_corrected_peak_time, _pmt_st_corrected_peak_time_rwm_ref; -}; - -sbnd::crt::CRTTopHatAnalysis::CRTTopHatAnalysis(fhicl::ParameterSet const& p) - : EDAnalyzer{p} -{ - fCRTStripHitModuleLabel = p.get("CRTStripHitModuleLabel", "crtstrips"); - fCRTClusterModuleLabel = p.get("CRTClusterModuleLabel", "crtclustering"); - fCRTSpacePointModuleLabel = p.get("CRTSpacePointModuleLabel", "crtspacepoints"); - fCRTTrackModuleLabel = p.get("CRTTrackModuleLabel", "crttracks"); - fPTBModuleLabel = p.get("PTBModuleLabel", "ptbdecoder"); - fTDCModuleLabel = p.get("TDCModuleLabel", "tdcdecoder"); - fTimingReferenceModuleLabel = p.get("TimingReferenceModuleLabel", "crtstrips"); - fPMTSoftwareTriggerModuleLabel = p.get("PMTSoftwareTriggerModuleLabel", "pmtmetricbnblight"); - fDebug = p.get("Debug", false); - fCutT0 = p.get("CutT0", false); - fSavePMTSoftwareTrigger = p.get("SavePMTSoftwareTrigger", false); - fMinT0 = p.get("MinT0", std::numeric_limits::min()); - fMaxT0 = p.get("MaxT0", std::numeric_limits::max()); - fAllowedPTBHLTs = p.get>("AllowedPTBHLTs", { 26, 27 }); - - art::ServiceHandle fs; - - fTree = fs->make("tree",""); - fTree->Branch("run", &_run); - fTree->Branch("subrun", &_subrun); - fTree->Branch("event", &_event); - fTree->Branch("crt_timing_reference_type", &_crt_timing_reference_type); - fTree->Branch("crt_timing_reference_channel", &_crt_timing_reference_channel); - - fTree->Branch("sh_channel", "std::vector", &_sh_channel); - fTree->Branch("sh_tagger", "std::vector", &_sh_tagger); - fTree->Branch("sh_ts0", "std::vector", &_sh_ts0); - fTree->Branch("sh_ts0_rwm_ref", "std::vector", &_sh_ts0_rwm_ref); - fTree->Branch("sh_ts0_ptb_hlt_beam_gate_ref", "std::vector", &_sh_ts0_ptb_hlt_beam_gate_ref); - fTree->Branch("sh_ts1", "std::vector", &_sh_ts1); - fTree->Branch("sh_ts1_rwm_ref", "std::vector", &_sh_ts1_rwm_ref); - fTree->Branch("sh_ts1_ptb_hlt_beam_gate_ref", "std::vector", &_sh_ts1_ptb_hlt_beam_gate_ref); - fTree->Branch("sh_unixs", "std::vector", &_sh_unixs); - fTree->Branch("sh_pos", "std::vector", &_sh_pos); - fTree->Branch("sh_err", "std::vector", &_sh_err); - fTree->Branch("sh_adc1", "std::vector", &_sh_adc1); - fTree->Branch("sh_adc2", "std::vector", &_sh_adc2); - fTree->Branch("sh_saturated1", "std::vector", &_sh_saturated1); - fTree->Branch("sh_saturated2", "std::vector", &_sh_saturated2); - - fTree->Branch("cl_ts0", "std::vector", &_cl_ts0); - fTree->Branch("cl_ts0_rwm_ref", "std::vector", &_cl_ts0_rwm_ref); - fTree->Branch("cl_ts0_ptb_hlt_beam_gate_ref", "std::vector", &_cl_ts0_ptb_hlt_beam_gate_ref); - fTree->Branch("cl_ts1", "std::vector", &_cl_ts1); - fTree->Branch("cl_ts1_rwm_ref", "std::vector", &_cl_ts1_rwm_ref); - fTree->Branch("cl_ts1_ptb_hlt_beam_gate_ref", "std::vector", &_cl_ts1_ptb_hlt_beam_gate_ref); - fTree->Branch("cl_unixs", "std::vector", &_cl_unixs); - fTree->Branch("cl_nhits", "std::vector", &_cl_nhits); - fTree->Branch("cl_tagger", "std::vector", &_cl_tagger); - fTree->Branch("cl_composition", "std::vector", &_cl_composition); - fTree->Branch("cl_has_sp", "std::vector", &_cl_has_sp); - fTree->Branch("cl_sp_x", "std::vector", &_cl_sp_x); - fTree->Branch("cl_sp_ex", "std::vector", &_cl_sp_ex); - fTree->Branch("cl_sp_y", "std::vector", &_cl_sp_y); - fTree->Branch("cl_sp_ey", "std::vector", &_cl_sp_ey); - fTree->Branch("cl_sp_z", "std::vector", &_cl_sp_z); - fTree->Branch("cl_sp_ez", "std::vector", &_cl_sp_ez); - fTree->Branch("cl_sp_pe", "std::vector", &_cl_sp_pe); - fTree->Branch("cl_sp_ts0", "std::vector", &_cl_sp_ts0); - fTree->Branch("cl_sp_ts0_rwm_ref", "std::vector", &_cl_sp_ts0_rwm_ref); - fTree->Branch("cl_sp_ts0_ptb_hlt_beam_gate_ref", "std::vector", &_cl_sp_ts0_ptb_hlt_beam_gate_ref); - fTree->Branch("cl_sp_ets0", "std::vector", &_cl_sp_ets0); - fTree->Branch("cl_sp_ts1", "std::vector", &_cl_sp_ts1); - fTree->Branch("cl_sp_ts1_rwm_ref", "std::vector", &_cl_sp_ts1_rwm_ref); - fTree->Branch("cl_sp_ts1_ptb_hlt_beam_gate_ref", "std::vector", &_cl_sp_ts1_ptb_hlt_beam_gate_ref); - fTree->Branch("cl_sp_ets1", "std::vector", &_cl_sp_ets1); - fTree->Branch("cl_sp_complete", "std::vector", &_cl_sp_complete); - - fTree->Branch("tr_start_x", "std::vector", &_tr_start_x); - fTree->Branch("tr_start_y", "std::vector", &_tr_start_y); - fTree->Branch("tr_start_z", "std::vector", &_tr_start_z); - fTree->Branch("tr_end_x", "std::vector", &_tr_end_x); - fTree->Branch("tr_end_y", "std::vector", &_tr_end_y); - fTree->Branch("tr_end_z", "std::vector", &_tr_end_z); - fTree->Branch("tr_dir_x", "std::vector", &_tr_dir_x); - fTree->Branch("tr_dir_y", "std::vector", &_tr_dir_y); - fTree->Branch("tr_dir_z", "std::vector", &_tr_dir_z); - fTree->Branch("tr_ts0", "std::vector", &_tr_ts0); - fTree->Branch("tr_ts0_rwm_ref", "std::vector", &_tr_ts0_rwm_ref); - fTree->Branch("tr_ts0_ptb_hlt_beam_gate_ref", "std::vector", &_tr_ts0_ptb_hlt_beam_gate_ref); - fTree->Branch("tr_ets0", "std::vector", &_tr_ets0); - fTree->Branch("tr_ts1", "std::vector", &_tr_ts1); - fTree->Branch("tr_ts1_rwm_ref", "std::vector", &_tr_ts1_rwm_ref); - fTree->Branch("tr_ts1_ptb_hlt_beam_gate_ref", "std::vector", &_tr_ts1_ptb_hlt_beam_gate_ref); - fTree->Branch("tr_ets1", "std::vector", &_tr_ets1); - fTree->Branch("tr_pe", "std::vector", &_tr_pe); - fTree->Branch("tr_length", "std::vector", &_tr_length); - fTree->Branch("tr_tof", "std::vector", &_tr_tof); - fTree->Branch("tr_theta", "std::vector", &_tr_theta); - fTree->Branch("tr_phi", "std::vector", &_tr_phi); - fTree->Branch("tr_triple", "std::vector", &_tr_triple); - fTree->Branch("tr_tagger1", "std::vector", &_tr_tagger1); - fTree->Branch("tr_tagger2", "std::vector", &_tr_tagger2); - fTree->Branch("tr_tagger3", "std::vector", &_tr_tagger3); - - fTree->Branch("ptb_hlt_trigger", "std::vector", &_ptb_hlt_trigger); - fTree->Branch("ptb_hlt_timestamp", "std::vector", &_ptb_hlt_timestamp); - fTree->Branch("ptb_llt_trigger", "std::vector", &_ptb_llt_trigger); - fTree->Branch("ptb_llt_timestamp", "std::vector", &_ptb_llt_timestamp); - - fTree->Branch("tdc_channel", "std::vector", &_tdc_channel); - fTree->Branch("tdc_timestamp", "std::vector", &_tdc_timestamp); - fTree->Branch("tdc_offset", "std::vector", &_tdc_offset); - fTree->Branch("tdc_name", "std::vector", &_tdc_name); - - fTree->Branch("etrig_good", &_etrig_good); - fTree->Branch("rwm_good", &_rwm_good); - fTree->Branch("ptb_hlt_beam_gate_good", &_ptb_hlt_beam_gate_good); - fTree->Branch("crt_t1_reset_good", &_crt_t1_reset_good); - fTree->Branch("rwm_etrig_diff", &_rwm_etrig_diff); - fTree->Branch("ptb_hlt_beam_gate_etrig_diff", &_ptb_hlt_beam_gate_etrig_diff); - fTree->Branch("rwm_crt_t1_reset_diff", &_rwm_crt_t1_reset_diff); - fTree->Branch("ptb_hlt_beam_gate_crt_t1_reset_diff", &_ptb_hlt_beam_gate_crt_t1_reset_diff); - fTree->Branch("rwm_ptb_hlt_beam_gate_diff", &_rwm_ptb_hlt_beam_gate_diff); - - if(fSavePMTSoftwareTrigger) - { - fTree->Branch("pmt_st_found_trigger", &_pmt_st_found_trigger); - fTree->Branch("pmt_st_corrected_peak_time", &_pmt_st_corrected_peak_time); - fTree->Branch("pmt_st_corrected_peak_time", &_pmt_st_corrected_peak_time); - fTree->Branch("pmt_st_corrected_peak_time_rwm_ref", &_pmt_st_corrected_peak_time_rwm_ref); - } -} - -void sbnd::crt::CRTTopHatAnalysis::analyze(art::Event const& e) -{ - _run = e.id().run(); - _subrun = e.id().subRun(); - _event = e.id().event(); - - _crt_timing_reference_type = -1; - _crt_timing_reference_channel = -1; - - art::Handle TimingReferenceHandle; - e.getByLabel(fTimingReferenceModuleLabel, TimingReferenceHandle); - if(TimingReferenceHandle.isValid()) - { - _crt_timing_reference_type = TimingReferenceHandle->timingType; - _crt_timing_reference_channel = TimingReferenceHandle->timingChannel; - } - - // Get PTBs - art::Handle> PTBHandle; - e.getByLabel(fPTBModuleLabel, PTBHandle); - if(!PTBHandle.isValid()){ - std::cout << "PTB product " << fPTBModuleLabel << " not found..." << std::endl; - throw std::exception(); - } - std::vector> PTBVec; - art::fill_ptr_vector(PTBVec, PTBHandle); - - // Fill PTB variables - AnalysePTBs(PTBVec); - - // Get TDCs - art::Handle> TDCHandle; - e.getByLabel(fTDCModuleLabel, TDCHandle); - if(!TDCHandle.isValid()){ - std::cout << "TDC product " << fTDCModuleLabel << " not found..." << std::endl; - throw std::exception(); - } - std::vector> TDCVec; - art::fill_ptr_vector(TDCVec, TDCHandle); - - // Fill TDC variables - AnalyseTDCs(TDCVec); - - SortReferencing(); - - // Get CRTStripHits - art::Handle> CRTStripHitHandle; - e.getByLabel(fCRTStripHitModuleLabel, CRTStripHitHandle); - if(!CRTStripHitHandle.isValid()){ - std::cout << "CRTStripHit product " << fCRTStripHitModuleLabel << " not found..." << std::endl; - throw std::exception(); - } - std::vector> CRTStripHitVec; - art::fill_ptr_vector(CRTStripHitVec, CRTStripHitHandle); - - // Fill CRTStripHit variables - AnalyseCRTStripHits(e, CRTStripHitVec); - - // Get CRTClusters - art::Handle> CRTClusterHandle; - e.getByLabel(fCRTClusterModuleLabel, CRTClusterHandle); - if(!CRTClusterHandle.isValid()){ - std::cout << "CRTCluster product " << fCRTClusterModuleLabel << " not found..." << std::endl; - throw std::exception(); - } - std::vector> CRTClusterVec; - art::fill_ptr_vector(CRTClusterVec, CRTClusterHandle); - - // Get CRTCluster to CRTSpacePoint Assns - art::FindManyP clustersToSpacePoints(CRTClusterHandle, e, fCRTSpacePointModuleLabel); - - // Fill CRTCluster variables - AnalyseCRTClusters(e, CRTClusterVec, clustersToSpacePoints); - - // Get CRTTracks - art::Handle> CRTTrackHandle; - e.getByLabel(fCRTTrackModuleLabel, CRTTrackHandle); - if(!CRTTrackHandle.isValid()){ - std::cout << "CRTTrack product " << fCRTTrackModuleLabel << " not found..." << std::endl; - throw std::exception(); - } - std::vector> CRTTrackVec; - art::fill_ptr_vector(CRTTrackVec, CRTTrackHandle); - - // Fill CRTTrack variables - AnalyseCRTTracks(e, CRTTrackVec); - - if(fSavePMTSoftwareTrigger) - { - // Get PMTSoftwareTriggers - art::Handle> PMTSoftwareTriggerHandle; - e.getByLabel(fPMTSoftwareTriggerModuleLabel, PMTSoftwareTriggerHandle); - if(!PMTSoftwareTriggerHandle.isValid()){ - std::cout << "PMTSoftwareTrigger product " << fPMTSoftwareTriggerModuleLabel << " not found..." << std::endl; - throw std::exception(); - } - std::vector> PMTSoftwareTriggerVec; - art::fill_ptr_vector(PMTSoftwareTriggerVec, PMTSoftwareTriggerHandle); - - // Fill PMTSoftwareTrigger variables - AnalysePMTSoftwareTriggers(e, PMTSoftwareTriggerVec); - } - - fTree->Fill(); -} - -void sbnd::crt::CRTTopHatAnalysis::AnalysePTBs(std::vector> &PTBVec) -{ - unsigned nHLTs = 0; - - for(auto const& ptb : PTBVec) - nHLTs += ptb->GetNHLTriggers(); - - _ptb_hlt_trigger.resize(nHLTs); - _ptb_hlt_timestamp.resize(nHLTs); - - unsigned hlt_i = 0; - - for(auto const& ptb : PTBVec) - { - for(unsigned i = 0; i < ptb->GetNHLTriggers(); ++i) - { - _ptb_hlt_trigger[hlt_i] = ptb->GetHLTrigger(i).trigger_word; - _ptb_hlt_timestamp[hlt_i] = ptb->GetHLTrigger(i).timestamp * 20; - - ++hlt_i; - } - } - - unsigned nLLTs = 0; - - for(auto const& ptb : PTBVec) - nLLTs += ptb->GetNLLTriggers(); - - _ptb_llt_trigger.resize(nLLTs); - _ptb_llt_timestamp.resize(nLLTs); - - unsigned llt_i = 0; - - for(auto const& ptb : PTBVec) - { - for(unsigned i = 0; i < ptb->GetNLLTriggers(); ++i) - { - _ptb_llt_trigger[llt_i] = ptb->GetLLTrigger(i).trigger_word; - _ptb_llt_timestamp[llt_i] = ptb->GetLLTrigger(i).timestamp * 20; - - ++llt_i; - } - } -} - -void sbnd::crt::CRTTopHatAnalysis::AnalyseTDCs(std::vector> &TDCVec) -{ - const unsigned nTDCs = TDCVec.size(); - - _tdc_channel.resize(nTDCs); - _tdc_timestamp.resize(nTDCs); - _tdc_offset.resize(nTDCs); - _tdc_name.resize(nTDCs); - - unsigned tdc_i = 0; - - for(auto const& tdc : TDCVec) - { - _tdc_channel[tdc_i] = tdc->Channel(); - _tdc_timestamp[tdc_i] = tdc->Timestamp(); - _tdc_offset[tdc_i] = tdc->Offset(); - _tdc_name[tdc_i] = tdc->Name(); - - ++tdc_i; - } -} - -void sbnd::crt::CRTTopHatAnalysis::SortReferencing() -{ - _etrig_good = false; _rwm_good = false; _ptb_hlt_beam_gate_good = false; _crt_t1_reset_good = false; - _rwm_etrig_diff = std::numeric_limits::max(); _ptb_hlt_beam_gate_etrig_diff = std::numeric_limits::max(); - _rwm_crt_t1_reset_diff = std::numeric_limits::max(); _ptb_hlt_beam_gate_crt_t1_reset_diff = std::numeric_limits::max(); - _rwm_ptb_hlt_beam_gate_diff = std::numeric_limits::max(); - - int etrig_count = 0, etrig_id = -1, rwm_count = 0, rwm_id = -1, crt_t1_reset_count = 0, crt_t1_reset_id = -1; - - for(unsigned int tdc_i = 0; tdc_i < _tdc_channel.size(); ++tdc_i) - { - if(_tdc_channel[tdc_i] == 4) - { - ++etrig_count; - etrig_id = tdc_i; - } - else if(_tdc_channel[tdc_i] == 2) - { - ++rwm_count; - rwm_id = tdc_i; - } - else if(_tdc_channel[tdc_i] == 0) - { - ++crt_t1_reset_count; - crt_t1_reset_id = tdc_i; - } - } - - uint64_t etrig = std::numeric_limits::max(), rwm = std::numeric_limits::max(), - hlt = std::numeric_limits::max(), crt_t1_reset = std::numeric_limits::max(); - - if(etrig_count == 1) - { - _etrig_good = true; - etrig = _tdc_timestamp[etrig_id]; - } - - if(rwm_count == 1) - { - _rwm_good = true; - rwm = _tdc_timestamp[rwm_id]; - } - - if(etrig_count == 1) - { - double closest_diff = std::numeric_limits::max(); - - for(unsigned int ptb_i = 0; ptb_i < _ptb_hlt_trigger.size(); ++ptb_i) - { - std::bitset<32> hlt_bitmask = std::bitset<32>(_ptb_hlt_trigger[ptb_i]); - - for(uint32_t allowed_hlt : fAllowedPTBHLTs) - { - if(hlt_bitmask[allowed_hlt]) - { - _ptb_hlt_beam_gate_good = true; - - uint64_t temp_hlt = _ptb_hlt_timestamp[ptb_i]; - double diff = etrig > temp_hlt ? etrig - temp_hlt : -1. * (temp_hlt - etrig); - - if(std::abs(diff) < closest_diff) - { - closest_diff = diff; - hlt = temp_hlt; - } - } - } - } - } - - if(crt_t1_reset_count == 1) - { - _crt_t1_reset_good = true; - crt_t1_reset = _tdc_timestamp[crt_t1_reset_id]; - } - - if(_etrig_good && _rwm_good) - _rwm_etrig_diff = etrig > rwm ? etrig - rwm : -1. * (rwm - etrig); - - if(_etrig_good && _ptb_hlt_beam_gate_good) - _ptb_hlt_beam_gate_etrig_diff = etrig > hlt ? etrig - hlt : -1. * (hlt - etrig); - - if(_crt_t1_reset_good && _rwm_good) - _rwm_crt_t1_reset_diff = crt_t1_reset > rwm ? crt_t1_reset - rwm : -1. * (rwm - crt_t1_reset); - - if(_etrig_good && _crt_t1_reset_good && _ptb_hlt_beam_gate_good) - _ptb_hlt_beam_gate_crt_t1_reset_diff = crt_t1_reset > hlt ? crt_t1_reset - hlt : -1. * (hlt - crt_t1_reset); - - if(_etrig_good && _rwm_good && _ptb_hlt_beam_gate_good) - _rwm_ptb_hlt_beam_gate_diff = hlt > rwm ? hlt - rwm : -1. * (rwm - hlt); -} - -void sbnd::crt::CRTTopHatAnalysis::AnalyseCRTStripHits(const art::Event &e, const std::vector> &CRTStripHitVec) -{ - _sh_channel.clear(); - _sh_tagger.clear(); - _sh_ts0.clear(); - _sh_ts0_rwm_ref.clear(); - _sh_ts0_ptb_hlt_beam_gate_ref.clear(); - _sh_ts1.clear(); - _sh_ts1_rwm_ref.clear(); - _sh_ts1_ptb_hlt_beam_gate_ref.clear(); - _sh_unixs.clear(); - _sh_pos.clear(); - _sh_err.clear(); - _sh_adc1.clear(); - _sh_adc2.clear(); - _sh_saturated1.clear(); - _sh_saturated2.clear(); - - for(auto const &hit : CRTStripHitVec) - { - if(fCutT0 && (hit->Ts0() < fMinT0 || hit->Ts0() > fMaxT0)) - continue; - - _sh_channel.push_back(hit->Channel()); - _sh_tagger.push_back(fCRTGeoService->ChannelToTaggerEnum(hit->Channel())); - _sh_ts0.push_back(hit->Ts0()); - _sh_ts0_rwm_ref.push_back(hit->Ts0() + _rwm_etrig_diff); - _sh_ts0_ptb_hlt_beam_gate_ref.push_back(hit->Ts0() + _ptb_hlt_beam_gate_etrig_diff); - _sh_ts1.push_back(hit->Ts1()); - _sh_ts1_rwm_ref.push_back(hit->Ts1() + _rwm_crt_t1_reset_diff); - _sh_ts1_ptb_hlt_beam_gate_ref.push_back(hit->Ts1() + _ptb_hlt_beam_gate_crt_t1_reset_diff); - _sh_unixs.push_back(hit->UnixS()); - _sh_pos.push_back(hit->Pos()); - _sh_err.push_back(hit->Error()); - _sh_adc1.push_back(hit->ADC1()); - _sh_adc2.push_back(hit->ADC2()); - _sh_saturated1.push_back(hit->Saturated1()); - _sh_saturated2.push_back(hit->Saturated2()); - } -} - -void sbnd::crt::CRTTopHatAnalysis::AnalyseCRTClusters(const art::Event &e, const std::vector> &CRTClusterVec, - const art::FindManyP &clustersToSpacePoints) -{ - _cl_ts0.clear(); - _cl_ts0_rwm_ref.clear(); - _cl_ts0_ptb_hlt_beam_gate_ref.clear(); - _cl_ts1.clear(); - _cl_ts1_rwm_ref.clear(); - _cl_ts1_ptb_hlt_beam_gate_ref.clear(); - _cl_unixs.clear(); - _cl_nhits.clear(); - _cl_tagger.clear(); - _cl_composition.clear(); - _cl_has_sp.clear(); - _cl_sp_x.clear(); - _cl_sp_ex.clear(); - _cl_sp_y.clear(); - _cl_sp_ey.clear(); - _cl_sp_z.clear(); - _cl_sp_ez.clear(); - _cl_sp_pe.clear(); - _cl_sp_ts0.clear(); - _cl_sp_ts0_rwm_ref.clear(); - _cl_sp_ts0_ptb_hlt_beam_gate_ref.clear(); - _cl_sp_ets0.clear(); - _cl_sp_ts1.clear(); - _cl_sp_ts1_rwm_ref.clear(); - _cl_sp_ts1_ptb_hlt_beam_gate_ref.clear(); - _cl_sp_ets1.clear(); - _cl_sp_complete.clear(); - - for(auto const &cluster : CRTClusterVec) - { - if(fCutT0 && (cluster->Ts0() < fMinT0 || cluster->Ts0() > fMaxT0)) - continue; - - _cl_ts0.push_back(cluster->Ts0()); - _cl_ts0_rwm_ref.push_back(cluster->Ts0() + _rwm_etrig_diff); - _cl_ts0_ptb_hlt_beam_gate_ref.push_back(cluster->Ts0() + _ptb_hlt_beam_gate_etrig_diff); - _cl_ts1.push_back(cluster->Ts1()); - _cl_ts1_rwm_ref.push_back(cluster->Ts1() + _rwm_crt_t1_reset_diff); - _cl_ts1_ptb_hlt_beam_gate_ref.push_back(cluster->Ts1() + _ptb_hlt_beam_gate_crt_t1_reset_diff); - _cl_unixs.push_back(cluster->UnixS()); - _cl_nhits.push_back(cluster->NHits()); - _cl_tagger.push_back(cluster->Tagger()); - _cl_composition.push_back(cluster->Composition()); - - const auto spacepoints = clustersToSpacePoints.at(cluster.key()); - if(spacepoints.size() == 1) - { - const auto spacepoint = spacepoints[0]; - - _cl_has_sp.push_back(true); - _cl_sp_x.push_back(spacepoint->X()); - _cl_sp_ex.push_back(spacepoint->XErr()); - _cl_sp_y.push_back(spacepoint->Y()); - _cl_sp_ey.push_back(spacepoint->YErr()); - _cl_sp_z.push_back(spacepoint->Z()); - _cl_sp_ez.push_back(spacepoint->ZErr()); - _cl_sp_pe.push_back(spacepoint->PE()); - _cl_sp_ts0.push_back(spacepoint->Ts0()); - _cl_sp_ts0_rwm_ref.push_back(spacepoint->Ts0() + _rwm_etrig_diff); - _cl_sp_ts0_ptb_hlt_beam_gate_ref.push_back(spacepoint->Ts0() + _ptb_hlt_beam_gate_etrig_diff); - _cl_sp_ets0.push_back(spacepoint->Ts0Err()); - _cl_sp_ts1.push_back(spacepoint->Ts1()); - _cl_sp_ts1_rwm_ref.push_back(spacepoint->Ts1() + _rwm_crt_t1_reset_diff); - _cl_sp_ts1_ptb_hlt_beam_gate_ref.push_back(spacepoint->Ts1() + _ptb_hlt_beam_gate_crt_t1_reset_diff); - _cl_sp_ets1.push_back(spacepoint->Ts1Err()); - _cl_sp_complete.push_back(spacepoint->Complete()); - } - else - { - _cl_has_sp.push_back(false); - _cl_sp_x.push_back(-999999.); - _cl_sp_ex.push_back(-999999.); - _cl_sp_y.push_back(-999999.); - _cl_sp_ey.push_back(-999999.); - _cl_sp_z.push_back(-999999.); - _cl_sp_ez.push_back(-999999.); - _cl_sp_pe.push_back(-999999.); - _cl_sp_ts0.push_back(-999999.); - _cl_sp_ts0_rwm_ref.push_back(-999999.); - _cl_sp_ts0_ptb_hlt_beam_gate_ref.push_back(-999999.); - _cl_sp_ets0.push_back(-999999.); - _cl_sp_ts1.push_back(-999999.); - _cl_sp_ts1_rwm_ref.push_back(-999999.); - _cl_sp_ts1_ptb_hlt_beam_gate_ref.push_back(-999999.); - _cl_sp_ets1.push_back(-999999.); - _cl_sp_complete.push_back(false); - } - } -} -void sbnd::crt::CRTTopHatAnalysis::AnalyseCRTTracks(const art::Event &e, const std::vector> &CRTTrackVec) -{ - _tr_start_x.clear(); - _tr_start_y.clear(); - _tr_start_z.clear(); - _tr_end_x.clear(); - _tr_end_y.clear(); - _tr_end_z.clear(); - _tr_dir_x.clear(); - _tr_dir_y.clear(); - _tr_dir_z.clear(); - _tr_ts0.clear(); - _tr_ts0_rwm_ref.clear(); - _tr_ts0_ptb_hlt_beam_gate_ref.clear(); - _tr_ets0.clear(); - _tr_ts1.clear(); - _tr_ts1_rwm_ref.clear(); - _tr_ts1_ptb_hlt_beam_gate_ref.clear(); - _tr_ets1.clear(); - _tr_pe.clear(); - _tr_length.clear(); - _tr_tof.clear(); - _tr_theta.clear(); - _tr_phi.clear(); - _tr_triple.clear(); - _tr_tagger1.clear(); - _tr_tagger2.clear(); - _tr_tagger3.clear(); - - for(auto const& track : CRTTrackVec) - { - if(fCutT0 && (track->Ts0() < fMinT0 || track->Ts0() > fMaxT0)) - continue; - - const geo::Point_t start = track->Start(); - _tr_start_x.push_back(start.X()); - _tr_start_y.push_back(start.Y()); - _tr_start_z.push_back(start.Z()); - - const geo::Point_t end = track->End(); - _tr_end_x.push_back(end.X()); - _tr_end_y.push_back(end.Y()); - _tr_end_z.push_back(end.Z()); - - const geo::Vector_t dir = track->Direction(); - _tr_dir_x.push_back(dir.X()); - _tr_dir_y.push_back(dir.Y()); - _tr_dir_z.push_back(dir.Z()); - - _tr_ts0.push_back(track->Ts0()); - _tr_ts0_rwm_ref.push_back(track->Ts0() + _rwm_etrig_diff); - _tr_ts0_ptb_hlt_beam_gate_ref.push_back(track->Ts0() + _ptb_hlt_beam_gate_etrig_diff); - _tr_ets0.push_back(track->Ts0Err()); - _tr_ts1.push_back(track->Ts1()); - _tr_ts1_rwm_ref.push_back(track->Ts1() + _rwm_crt_t1_reset_diff); - _tr_ts1_ptb_hlt_beam_gate_ref.push_back(track->Ts1() + _ptb_hlt_beam_gate_crt_t1_reset_diff); - _tr_ets1.push_back(track->Ts1Err()); - _tr_pe.push_back(track->PE()); - _tr_length.push_back(track->Length()); - _tr_tof.push_back(track->ToF()); - _tr_theta.push_back(TMath::RadToDeg() * track->Theta()); - _tr_phi.push_back(TMath::RadToDeg() * track->Phi()); - _tr_triple.push_back(track->Triple()); - - unsigned tag_i = 0; - - for(auto const &tagger : track->Taggers()) - { - if(tag_i == 0) - _tr_tagger1.push_back(tagger); - else if(tag_i == 1) - _tr_tagger2.push_back(tagger); - else if(tag_i == 2) - _tr_tagger3.push_back(tagger); - - ++tag_i; - } - } -} - -void sbnd::crt::CRTTopHatAnalysis::AnalysePMTSoftwareTriggers(const art::Event &e, const std::vector> &PMTSoftwareTriggerVec) -{ - _pmt_st_found_trigger = false; - _pmt_st_corrected_peak_time = std::numeric_limits::lowest(); - _pmt_st_corrected_peak_time_rwm_ref = std::numeric_limits::lowest(); - - if(PMTSoftwareTriggerVec.size() != 1) - return; - - _pmt_st_found_trigger = PMTSoftwareTriggerVec[0]->foundBeamTrigger; - _pmt_st_corrected_peak_time = PMTSoftwareTriggerVec[0]->peaktime*1e3 + PMTSoftwareTriggerVec[0]->trig_ts; - _pmt_st_corrected_peak_time_rwm_ref = _pmt_st_corrected_peak_time + _rwm_ptb_hlt_beam_gate_diff; -} - -DEFINE_ART_MODULE(sbnd::crt::CRTTopHatAnalysis) diff --git a/sbndcode/CRT/CRTAna/crttophatana_sbnd.fcl b/sbndcode/CRT/CRTAna/crttophatana_sbnd.fcl deleted file mode 100644 index a82b14e43..000000000 --- a/sbndcode/CRT/CRTAna/crttophatana_sbnd.fcl +++ /dev/null @@ -1,12 +0,0 @@ -BEGIN_PROLOG - -crttophatana_data_sbnd: -{ - module_type: "CRTTopHatAnalysis" - CutT0: true - MinT0: -50000 - MaxT0: 50000 - SavePMTSoftwareTrigger: true -} - -END_PROLOG diff --git a/sbndcode/CRT/CRTAna/run_crttophatana_data.fcl b/sbndcode/CRT/CRTAna/run_crttophatana_data.fcl deleted file mode 100644 index cce367369..000000000 --- a/sbndcode/CRT/CRTAna/run_crttophatana_data.fcl +++ /dev/null @@ -1,28 +0,0 @@ -#include "services_sbnd.fcl" -#include "crt_services_sbnd.fcl" -#include "crttophatana_sbnd.fcl" - -process_name: CRTTopHatAna - -services: -{ - TFileService: { fileName: "crttophatana_sbnd.root" } - @table::sbnd_basic_services - @table::crt_services_data_sbnd -} - -source: -{ - module_type: RootInput -} - -physics: -{ - analyzers: - { - crttophatana: @local::crttophatana_data_sbnd - } - - ana: [ crttophatana ] - end_paths: [ ana ] -} From cb47ee9171633c83ae098ccb6694115edfa91bce Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Fri, 27 Feb 2026 05:32:58 -0600 Subject: [PATCH 24/31] Remove reference to my data area --- sbndcode/CRT/CRTAna/adrift_sbnd.fcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbndcode/CRT/CRTAna/adrift_sbnd.fcl b/sbndcode/CRT/CRTAna/adrift_sbnd.fcl index 0be839450..8113032ed 100644 --- a/sbndcode/CRT/CRTAna/adrift_sbnd.fcl +++ b/sbndcode/CRT/CRTAna/adrift_sbnd.fcl @@ -10,7 +10,7 @@ adrift_data_sbnd: CRTTrackModuleLabel: "crttracks" DAQHeaderModuleLabel: "daq" DAQHeaderInstanceLabel: "RawEventHeader" - TopSaveDirectory: "/exp/sbnd/data/users/hlay/crt_comm_summer_2024/plots/adrift" + TopSaveDirectory: "/ENTER/YOUR/SAVE/DIRECTORY/HERE" Only2HitSpacePoints: false SaveAllFits: false SaveBadFits: false From bdf38e4bdde296074246f68ec0f6189ac1a637b9 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Fri, 27 Feb 2026 05:44:38 -0600 Subject: [PATCH 25/31] Reduce code duplication --- sbndcode/CRT/CRTAna/CRTAnalysis_module.cc | 42 ++++++----------------- sbndcode/CRT/CRTAna/crtana_sbnd.fcl | 24 ++++++------- 2 files changed, 22 insertions(+), 44 deletions(-) diff --git a/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc b/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc index 08b1f8202..4849708f2 100644 --- a/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc +++ b/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc @@ -37,13 +37,13 @@ #include "sbnobj/SBND/Timing/DAQTimestamp.hh" #include "sbndcode/Geometry/GeometryWrappers/CRTGeoService.h" -#include "sbndcode/Geometry/GeometryWrappers/TPCGeoAlg.h" #include "sbndcode/ChannelMaps/CRT/CRTChannelMapService.h" #include "sbndcode/CRT/CRTBackTracker/CRTBackTrackerAlg.h" #include "sbndcode/CRT/CRTUtils/CRTCommonUtils.h" #include "sbndcode/CRT/CRTUtils/TPCGeoUtil.h" #include "sbndcode/Decoders/PTB/sbndptb.h" #include "sbndcode/Timing/SBNDRawTimingObj.h" +#include "sbndcode/CRT/CRTReco/CRTClusterCharacterisationAlg.h" namespace sbnd::crt { class CRTAnalysis; @@ -103,16 +103,14 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { art::ServiceHandle fCRTGeoService; art::ServiceHandle fCRTChannelMapService; - TPCGeoAlg fTPCGeoAlg; - CRTBackTrackerAlg fCRTBackTrackerAlg; + CRTBackTrackerAlg fCRTBackTrackerAlg; + CRTClusterCharacterisationAlg fCRTClusterCharacAlg; std::string fMCParticleModuleLabel, fSimDepositModuleLabel, fFEBDataModuleLabel, fCRTStripHitModuleLabel, fCRTClusterModuleLabel, fCRTSpacePointModuleLabel, fCRTTrackModuleLabel, fCRTBlobModuleLabel, fTPCTrackModuleLabel, fCRTSpacePointMatchingModuleLabel, fCRTTrackMatchingModuleLabel, fPFPModuleLabel, fPTBModuleLabel, fTDCModuleLabel, fTimingReferenceModuleLabel; bool fDebug, fDataMode, fNoTPC, fHasPTB, fHasTDC, fHasBlobs, fTruthMatch; - //! Adding some of the reco parameters to save corrections - double fPEAttenuation, fTimeWalkNorm, fTimeWalkScale, fPropDelay; TTree* fTree; @@ -197,11 +195,11 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { std::vector _cl_composition; std::vector> _cl_channel_set; std::vector> _cl_adc_set; - std::vector> _cl_sh_ts0_set; //! To store t0 from x-y coincidences - std::vector> _cl_sh_ts1_set; //! To store t1 from x-y coincidences - std::vector> _cl_sh_feb_mac5_set; //! MAC5 addresses of StripHit FEBs - std::vector> _cl_sh_time_walk_set; //! Time walk correction - std::vector> _cl_sh_prop_delay_set; //! Light propagation correction + std::vector> _cl_sh_ts0_set; + std::vector> _cl_sh_ts1_set; + std::vector> _cl_sh_feb_mac5_set; + std::vector> _cl_sh_time_walk_set; + std::vector> _cl_sh_prop_delay_set; std::vector _cl_truth_trackid; std::vector _cl_truth_completeness; std::vector _cl_truth_purity; @@ -372,6 +370,7 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { sbnd::crt::CRTAnalysis::CRTAnalysis(fhicl::ParameterSet const& p) : EDAnalyzer{p} , fCRTBackTrackerAlg(p.get("CRTBackTrackerAlg", fhicl::ParameterSet())) + , fCRTClusterCharacAlg(p.get("CRTClusterCharacterisationAlg", fhicl::ParameterSet())) { fMCParticleModuleLabel = p.get("MCParticleModuleLabel", "largeant"); fSimDepositModuleLabel = p.get("SimDepositModuleLabel", "genericcrt"); @@ -395,10 +394,6 @@ sbnd::crt::CRTAnalysis::CRTAnalysis(fhicl::ParameterSet const& p) fHasTDC = p.get("HasTDC", false); fHasBlobs = p.get("HasBlobs", false); fTruthMatch = p.get("TruthMatch", true); - fPEAttenuation = p.get("PEAttenuation", 1.0); - fTimeWalkNorm = p.get("TimeWalkNorm", 0.0); - fTimeWalkScale = p.get("TimeWalkScale", 0.0); - fPropDelay = p.get("PropDelay", 0.0); if(!fDataMode && fTruthMatch) fCRTBackTrackerAlg = CRTBackTrackerAlg(p.get("CRTBackTrackerAlg", fhicl::ParameterSet())); @@ -1328,25 +1323,10 @@ void sbnd::crt::CRTAnalysis::AnalyseCRTClusters(const art::Event &e, const std:: _cl_sh_ts1_set[i][ii] = striphit->Ts1(); _cl_sh_feb_mac5_set[i][ii] = fCRTChannelMapService->GetMAC5FromOfflineChannelID(striphit->Channel()); - /* - * The below segment reimplements the CorrectTime() method - * from CRTReco/CRTClusterCharacterisationAlg.cc . - * Because the Ts0(), Ts1() getters invoked in _cl_sp_ts*, _cl_sh_ts*_set are raw T0/1 - * counters, the time walk and propagation delay are saved as explicit branches here. - */ if(spacepoints.size() == 1) { - double pe0 = fCRTGeoService->GetSiPM( striphit->Channel() ).gain * striphit->ADC1(); - double pe1 = fCRTGeoService->GetSiPM( striphit->Channel() + 1 ).gain * striphit->ADC2(); - double pe = pe0 + pe1; - - double dist = fCRTGeoService->DistanceDownStrip( spacepoints[0]->Pos(), striphit->Channel() ); - - double corr = std::pow( dist - fPEAttenuation, 2.0 ) / std::pow( fPEAttenuation, 2.0 ); - double tw_pe = pe * corr; - - _cl_sh_time_walk_set[i][ii] = fTimeWalkNorm * std::exp( -fTimeWalkScale * tw_pe ); - _cl_sh_prop_delay_set[i][ii] = fPropDelay * dist; + _cl_sh_time_walk_set[i][ii] = fCRTClusterCharacAlg.TimeWalk(striphit, spacepoints[0]->Pos()); + _cl_sh_prop_delay_set[i][ii] = fCRTClusterCharacAlg.PropagationDelay(striphit, spacepoints[0]->Pos()); ts0_set.push_back({_cl_sh_feb_mac5_set[i][ii], _cl_sh_ts0_set[i][ii] - _cl_sh_time_walk_set[i][ii] - _cl_sh_prop_delay_set[i][ii]}); ts1_set.push_back({_cl_sh_feb_mac5_set[i][ii], _cl_sh_ts1_set[i][ii] - _cl_sh_time_walk_set[i][ii] - _cl_sh_prop_delay_set[i][ii]}); diff --git a/sbndcode/CRT/CRTAna/crtana_sbnd.fcl b/sbndcode/CRT/CRTAna/crtana_sbnd.fcl index 1ab588870..f319bc4df 100644 --- a/sbndcode/CRT/CRTAna/crtana_sbnd.fcl +++ b/sbndcode/CRT/CRTAna/crtana_sbnd.fcl @@ -1,24 +1,22 @@ #include "crtbacktrackeralg_sbnd.fcl" -#include "crtsimmodules_sbnd.fcl" +#include "crtrecoproducers_sbnd.fcl" BEGIN_PROLOG crtana_sbnd: { - CRTBackTrackerAlg: @local::crtbacktrackeralg_sbnd - PEAttenuation: @local::sbnd_crtsim.DetSimParams.NpeScaleShift - PropDelay: @local::sbnd_crtsim.DetSimParams.PropDelay - TimeWalkNorm: @local::sbnd_crtsim.DetSimParams.TDelayNorm - TimeWalkScale: @local::sbnd_crtsim.DetSimParams.TDelayScale - TruthMatch: false - module_type: "CRTAnalysis" + CRTBackTrackerAlg: @local::crtbacktrackeralg_sbnd + CRTClusterCharacterisationAlg: @local::crtclustercharacterisationalg_sbnd + TruthMatch: false + module_type: "CRTAnalysis" } crtana_data_sbnd: @local::crtana_sbnd -crtana_data_sbnd.FEBDataModuleLabel: "crtdecoder" -crtana_data_sbnd.DataMode: true -crtana_data_sbnd.NoTPC: false -crtana_data_sbnd.HasPTB: true -crtana_data_sbnd.HasTDC: true +crtana_data_sbnd.FEBDataModuleLabel: "crtdecoder" +crtana_data_sbnd.DataMode: true +crtana_data_sbnd.NoTPC: false +crtana_data_sbnd.HasPTB: true +crtana_data_sbnd.HasTDC: true +crtana_data_sbnd.CRTClusterCharacterisationAlg: @local::crtclustercharacterisationalg_data_sbnd END_PROLOG From 8efaff2023309dda9eee806bbcfdb64b12df2cda Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Fri, 27 Feb 2026 05:56:51 -0600 Subject: [PATCH 26/31] Correct some very old naming problems --- sbndcode/CRT/CRTReco/CRTClusterCharacterisationAlg.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sbndcode/CRT/CRTReco/CRTClusterCharacterisationAlg.h b/sbndcode/CRT/CRTReco/CRTClusterCharacterisationAlg.h index 373d47ed7..97b3133f7 100644 --- a/sbndcode/CRT/CRTReco/CRTClusterCharacterisationAlg.h +++ b/sbndcode/CRT/CRTReco/CRTClusterCharacterisationAlg.h @@ -1,10 +1,9 @@ -#ifndef CRTBACKTRACKERALG_H_SEEN -#define CRTBACKTRACKERALG_H_SEEN +#ifndef CRTCLUSTERCHARACTERISATIONALG_H_SEEN +#define CRTCLUSTERCHARACTERISATIONALG_H_SEEN /////////////////////////////////////////////// // CRTClusterCharacterisationAlg.h // -// Truth Matching Utilities for CRT analysis // Henry Lay (h.lay@lancaster.ac.uk) // November 2022 /////////////////////////////////////////////// From 076fc35a786403595db0e3aacc41c4cbdba03c38 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Tue, 3 Mar 2026 07:25:01 -0600 Subject: [PATCH 27/31] Add rate for tracks of limited angle --- sbndcode/CRT/CRTAna/ADRIFT_module.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sbndcode/CRT/CRTAna/ADRIFT_module.cc b/sbndcode/CRT/CRTAna/ADRIFT_module.cc index 01727c94a..8725c472d 100644 --- a/sbndcode/CRT/CRTAna/ADRIFT_module.cc +++ b/sbndcode/CRT/CRTAna/ADRIFT_module.cc @@ -117,7 +117,7 @@ class sbnd::crt::ADRIFT : public art::EDAnalyzer { uint64_t _unix_start, _unix_end; int _n_events, _channel, _gdml_id, _mac5, _raw_channel, _tagger, _channel_status; double _area, _y_average, _ped_calib, _gain_calib, _ped_fit, _ped_fit_std, _ped_fit_chi2, _ped_peak, - _ped_reset_fit, _ped_reset_fit_std, _ped_reset_fit_chi2, _ped_reset_peak, _raw_max_chan_rate, _sh_rate, _sp_rate, _tr_rate, + _ped_reset_fit, _ped_reset_fit_std, _ped_reset_fit_chi2, _ped_reset_peak, _raw_max_chan_rate, _sh_rate, _sp_rate, _tr_rate, _tr_lim_angle_rate, _sh_peak_fit, _sh_peak_fit_chi2, _sh_peak_peak, _sh_pe_peak_fit, _sh_pe_peak_fit_chi2, _sh_pe_peak_peak, _sh_sat_rate, _sh_sat_ratio_total, _sh_sat_ratio_peak, _sp_peak_fit, _sp_peak_fit_chi2, _sp_peak_peak, _sp_pe_peak_fit, _sp_pe_peak_fit_chi2, _sp_pe_peak_peak, _sp_sat_rate, _sp_sat_ratio_total, _sp_sat_ratio_peak, @@ -270,6 +270,7 @@ sbnd::crt::ADRIFT::ADRIFT(fhicl::ParameterSet const& p) } if(fTrackLA) { + fChannelTree->Branch("tr_lim_angle_rate", &_tr_lim_angle_rate); fChannelTree->Branch("tr_lim_angle_peak_fit", &_tr_lim_angle_peak_fit); fChannelTree->Branch("tr_lim_angle_peak_fit_chi2", &_tr_lim_angle_peak_fit_chi2); fChannelTree->Branch("tr_lim_angle_peak_fit_converged", &_tr_lim_angle_peak_fit_converged); @@ -992,6 +993,8 @@ void sbnd::crt::ADRIFT::ProcessEntry(const int ch, const int window) if(fTrackLA && _tagger != kBottomTagger) { + Rate(hADCTrLA[window][ch], _tr_lim_angle_rate, window, fReconstructionWindow); + PeakPeak(hADCTrLA[window][ch], _ped_calib, _tr_lim_angle_peak_peak); PeakFit(hADCTrLA[window][ch], _tr_lim_angle_peak_peak, _ped_calib, _tr_lim_angle_peak_fit, _tr_lim_angle_peak_fit_chi2, _tr_lim_angle_peak_fit_converged, _channel_status, window); @@ -1302,6 +1305,7 @@ void sbnd::crt::ADRIFT::ResetVars() _tr_by_length_peak_fit = std::numeric_limits::lowest(); _tr_by_length_peak_fit_chi2 = std::numeric_limits::lowest(); _tr_by_length_peak_peak = std::numeric_limits::lowest(); + _tr_lim_angle_rate = std::numeric_limits::lowest(); _tr_lim_angle_peak_fit = std::numeric_limits::lowest(); _tr_lim_angle_peak_fit_chi2 = std::numeric_limits::lowest(); _tr_lim_angle_peak_peak = std::numeric_limits::lowest(); From c505fdaec1a03b3cb95f3e51e55bd86253578de7 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Tue, 3 Mar 2026 07:25:24 -0600 Subject: [PATCH 28/31] Add xshift for CRT-TPC track matching --- sbndcode/CRT/CRTAna/CRTAnalysis_module.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc b/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc index 4849708f2..318553eca 100644 --- a/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc +++ b/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc @@ -342,6 +342,7 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { std::vector _tpc_tr_matchable; std::vector _tpc_tr_matched; std::vector _tpc_tr_good_match; + std::vector _tpc_tr_xshift; std::vector _tpc_tr_ts0; std::vector _tpc_tr_ts1; std::vector> _tpc_tr_taggers; @@ -630,6 +631,7 @@ sbnd::crt::CRTAnalysis::CRTAnalysis(fhicl::ParameterSet const& p) fTree->Branch("tpc_sp_z", "std::vector", &_tpc_sp_z); fTree->Branch("tpc_sp_score", "std::vector", &_tpc_sp_score); fTree->Branch("tpc_tr_matched", "std::vector", &_tpc_tr_matched); + fTree->Branch("tpc_tr_xshift", "std::vector", &_tpc_tr_xshift); fTree->Branch("tpc_tr_ts0", "std::vector", &_tpc_tr_ts0); fTree->Branch("tpc_tr_ts1", "std::vector", &_tpc_tr_ts1); fTree->Branch("tpc_tr_taggers", "std::vector>", &_tpc_tr_taggers); @@ -1685,6 +1687,7 @@ void sbnd::crt::CRTAnalysis::AnalyseTPCMatching(const art::Event &e, const art:: _tpc_tr_matchable.resize(nTracks); _tpc_tr_matched.resize(nTracks); _tpc_tr_good_match.resize(nTracks); + _tpc_tr_xshift.resize(nTracks); _tpc_tr_ts0.resize(nTracks); _tpc_tr_ts1.resize(nTracks); _tpc_tr_taggers.resize(nTracks); @@ -1797,7 +1800,11 @@ void sbnd::crt::CRTAnalysis::AnalyseTPCMatching(const art::Event &e, const art:: { const anab::T0 trackMatch = tracksToTrackMatches.data(track.key()).ref(); + const int driftDirection = TPCGeoUtil::DriftDirectionFromHits(geometryService, trackHits); + const double crtShiftingTime = fDataMode ? crttrack->Ts0() * 1e-3 : crttrack->Ts1() * 1e-3; + _tpc_tr_matched[nActualTracks] = true; + _tpc_tr_xshift[nActualTracks] = driftDirection * crtShiftingTime * detProp.DriftVelocity(); _tpc_tr_ts0[nActualTracks] = crttrack->Ts0(); _tpc_tr_ts1[nActualTracks] = crttrack->Ts1(); _tpc_tr_score[nActualTracks] = trackMatch.TriggerConfidence(); @@ -1821,6 +1828,7 @@ void sbnd::crt::CRTAnalysis::AnalyseTPCMatching(const art::Event &e, const art:: else { _tpc_tr_matched[nActualTracks] = false; + _tpc_tr_xshift[nActualTracks] = -std::numeric_limits::max(); _tpc_tr_ts0[nActualTracks] = -std::numeric_limits::max(); _tpc_tr_ts1[nActualTracks] = -std::numeric_limits::max(); _tpc_tr_score[nActualTracks] = -std::numeric_limits::max(); From 2771a929c487217817ca66e1cda783d68aafcbe1 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Thu, 5 Mar 2026 05:15:09 -0600 Subject: [PATCH 29/31] Add track direction branches to spacepoint timing tree --- .../CRT/CRTAna/CRTTimingAnalysis_module.cc | 38 +++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc b/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc index 73846af9c..f050cce6c 100644 --- a/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc +++ b/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc @@ -70,7 +70,8 @@ class sbnd::crt::CRTTimingAnalysis : public art::EDAnalyzer { void AnalyseCRTSpacePoints(const std::vector> &CRTSpacePointVec, const art::FindOneP &spacepointsToClusters, - const art::FindManyP &clustersToStripHits); + const art::FindManyP &clustersToStripHits, + const art::FindOneP &spacepointsToTracks); void ResetSPVariables(); @@ -171,6 +172,9 @@ class sbnd::crt::CRTTimingAnalysis : public art::EDAnalyzer { std::vector _sp_sh_calib_offset_ts0_set; std::vector _sp_sh_cable_length_ts1_set; std::vector _sp_sh_calib_offset_ts1_set; + bool _sp_has_track; + double _sp_norm_angle; + double _sp_path_length; double _tr_start_x; double _tr_start_y; @@ -324,6 +328,9 @@ sbnd::crt::CRTTimingAnalysis::CRTTimingAnalysis(fhicl::ParameterSet const& p) fSPTree->Branch("sp_sh_calib_offset_ts0_set", "std::vector", &_sp_sh_calib_offset_ts0_set); fSPTree->Branch("sp_sh_cable_length_ts1_set", "std::vector", &_sp_sh_cable_length_ts1_set); fSPTree->Branch("sp_sh_calib_offset_ts1_set", "std::vector", &_sp_sh_calib_offset_ts1_set); + fSPTree->Branch("sp_has_track", &_sp_has_track); + fSPTree->Branch("sp_norm_angle", &_sp_norm_angle); + fSPTree->Branch("sp_path_length", &_sp_path_length); fTrTree = fs->make("tracks",""); fTrTree->Branch("run", &_run); @@ -495,6 +502,9 @@ void sbnd::crt::CRTTimingAnalysis::analyze(art::Event const& e) // Get CRTSpacePoint to CRTCluster Assns art::FindOneP spacepointsToClusters(CRTSpacePointHandle, e, fCRTSpacePointModuleLabel); + // Get CRTSpacePoint to CRTTrack Assns + art::FindOneP spacepointsToTracks(CRTSpacePointHandle, e, fCRTTrackModuleLabel); + // Get CRTClusters art::Handle> CRTClusterHandle; e.getByLabel(fCRTClusterModuleLabel, CRTClusterHandle); @@ -507,7 +517,7 @@ void sbnd::crt::CRTTimingAnalysis::analyze(art::Event const& e) art::FindManyP clustersToStripHits(CRTClusterHandle, e, fCRTClusterModuleLabel); // Fill CRTSpacePoint variables - AnalyseCRTSpacePoints(CRTSpacePointVec, spacepointsToClusters, clustersToStripHits); + AnalyseCRTSpacePoints(CRTSpacePointVec, spacepointsToClusters, clustersToStripHits, spacepointsToTracks); // Get CRTTracks art::Handle> CRTTrackHandle; @@ -736,13 +746,15 @@ void sbnd::crt::CRTTimingAnalysis::SortReferencing() void sbnd::crt::CRTTimingAnalysis::AnalyseCRTSpacePoints(const std::vector> &CRTSpacePointVec, const art::FindOneP &spacepointsToClusters, - const art::FindManyP &clustersToStripHits) + const art::FindManyP &clustersToStripHits, + const art::FindOneP &spacepointsToTracks) { for(auto const& sp : CRTSpacePointVec) { ResetSPVariables(); const art::Ptr cl = spacepointsToClusters.at(sp.key()); + const art::Ptr tr = spacepointsToTracks.at(sp.key()); const std::vector> shs = clustersToStripHits.at(cl.key()); const unsigned n_shs = shs.size(); @@ -790,6 +802,23 @@ void sbnd::crt::CRTTimingAnalysis::AnalyseCRTSpacePoints(const std::vectorDirection().X(), tr->Direction().Y(), tr->Direction().Z()); + _sp_norm_angle = TMath::RadToDeg() * normal.Angle(tr_dir); + _sp_path_length = 1. / TMath::Cos(normal.Angle(tr_dir)); + } + fSPTree->Fill(); fSPTaggerMap[sp.key()] = _sp_tagger; @@ -824,8 +853,11 @@ void sbnd::crt::CRTTimingAnalysis::ResetSPVariables() _sp_ts1_rwm_ref_front_face = std::numeric_limits::lowest(); _sp_ts1_ptb_hlt_beam_gate_ref_front_face = std::numeric_limits::lowest(); _sp_dts1 = std::numeric_limits::lowest(); + _sp_norm_angle = std::numeric_limits::lowest(); + _sp_path_length = std::numeric_limits::lowest(); _sp_single_timing_chain = false; + _sp_has_track = false; _sp_sh_channel_set.clear(); _sp_sh_mac5_set.clear(); From a8353e26486a6b18c90e1a44f6ff3aa0bee39a48 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Thu, 5 Mar 2026 05:20:36 -0600 Subject: [PATCH 30/31] If we're going to do comments lets get them right --- sbndcode/CRT/CRTAna/CRTAnalysis_module.cc | 24 ++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc b/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc index 318553eca..7c26b2421 100644 --- a/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc +++ b/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc @@ -122,7 +122,7 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { int _crt_timing_reference_type; int _crt_timing_reference_channel; - //mc truth + // True Particles (from G4) std::vector _mc_trackid; std::vector _mc_pdg; std::vector _mc_status; @@ -145,7 +145,7 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { std::vector _mc_endpz; std::vector _mc_ende; - //G4 detector id + // True Energy Depositions std::vector _ide_trackid; std::vector _ide_e; std::vector _ide_entryx; @@ -157,7 +157,7 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { std::vector _ide_exitz; std::vector _ide_exitt; - //front end mother board + // Raw Readouts (FEBDatas) std::vector _feb_mac5; std::vector _feb_tagger; std::vector _feb_flags; @@ -167,7 +167,7 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { std::vector> _feb_adc; std::vector _feb_coinc; - //strip hit to select the strip which has ADC above threshold + // Strip Hits std::vector _sh_channel; std::vector _sh_tagger; std::vector _sh_ts0; @@ -186,7 +186,7 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { std::vector _sh_truth_energy; std::vector _sh_truth_time; - //cluster from x-y coincidence for CRTSpacePoint , this is what we normally call a CRT hit + // Clusters and their corresponding SpacePoints std::vector _cl_ts0; std::vector _cl_ts1; std::vector _cl_unixs; @@ -232,7 +232,7 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { std::vector _cl_sp_dts1; std::vector _cl_sp_complete; - //backtrack truth information from reco level + // True Deposits per particle per tagger std::vector _td_tag_trackid; std::vector _td_tag_pdg; std::vector _td_tag_tagger; @@ -243,6 +243,7 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { std::vector _td_tag_z; std::vector _td_tag_reco_status; + // True Deposits per particle std::vector _td_trackid; std::vector _td_pdg; std::vector _td_energy; @@ -251,7 +252,7 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { std::vector _td_reco_status; std::vector _td_reco_triple; - //track level information + // Tracks std::vector _tr_start_x; std::vector _tr_start_y; std::vector _tr_start_z; @@ -297,7 +298,7 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { std::vector _tr_truth_theta; std::vector _tr_truth_phi; - // crt blob information + // Blobs std::vector _bl_ts0; std::vector _bl_ets0; std::vector _bl_ts1; @@ -306,7 +307,7 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { std::vector _bl_nsps; std::vector> _bl_nsps_per_tagger; - // tpc track information (including crt matching) + // TPC Tracks and their CRT matches std::vector _tpc_start_x; std::vector _tpc_start_y; std::vector _tpc_start_z; @@ -354,14 +355,15 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { std::vector _tpc_tr_end_z; std::vector _tpc_tr_score; - // ptb information (trigger board) + // Penn Trigger Board HLTs std::vector _ptb_hlt_trigger; std::vector _ptb_hlt_timestamp; + // Penn Trigger Board LLTs std::vector _ptb_llt_trigger; std::vector _ptb_llt_timestamp; - // spec tdc information (timing board) + // SPEC TDC Timestamps std::vector _tdc_channel; std::vector _tdc_timestamp; std::vector _tdc_offset; From 1dd3071b79f40903c3253879d0b5fa5302546c3c Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Thu, 5 Mar 2026 05:20:53 -0600 Subject: [PATCH 31/31] Add README to point to documentation --- sbndcode/CRT/CRTAna/README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 sbndcode/CRT/CRTAna/README.md diff --git a/sbndcode/CRT/CRTAna/README.md b/sbndcode/CRT/CRTAna/README.md new file mode 100644 index 000000000..7b7e26cf3 --- /dev/null +++ b/sbndcode/CRT/CRTAna/README.md @@ -0,0 +1,3 @@ +# CRT Analysis Modules + +Details of these modules and the outputs (trees, branches, histograms) can be found in [docDB#45886](https://sbn-docdb.fnal.gov/cgi-bin/sso/ShowDocument?docid=45886)