Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
cf3624f
add WireMod in X vs theta_XW
hausnerh Jan 13, 2026
84c116d
I believe this is the correct ThXW calculation...
hausnerh Feb 3, 2026
e8ecc06
Slight tweak to ThXW so it's calc'd once
hausnerh Mar 9, 2026
a28c498
bug fixes to the WM util + slightly smarting handling to the EDep pro…
hausnerh Mar 26, 2026
8bafd5a
fix a few spaces & typos
hausnerh Mar 30, 2026
ce4b9cc
Catch and ignore non-active energy depositions.
gputnam Apr 1, 2026
1df46ba
Merge pull request #640 from SBNSoftware/feature/hhausner_wiremod_xxw…
hausnerh Apr 1, 2026
cd921e7
Fix ThetaZ/angletovert discrepency in calculating the pitch
hausnerh Apr 22, 2026
0368412
add pathological check on small q_orig scaling
hausnerh May 26, 2026
990e237
Remove unnecessary round when converting from ChannelROI back to Wire.
gputnam May 26, 2026
62647a2
Hide q_orig warning under verbose. Add in sigma_distance check.
gputnam May 26, 2026
f5c291c
Add in bad channel check to sbncode Hit Finder port.
gputnam May 26, 2026
b4f672e
Analysis module to check that bad channels are not being reconstructe…
gputnam May 26, 2026
5d818ed
Fix sq code.
gputnam May 26, 2026
15a8825
Fix WM sigma cut to 3^2=9.
gputnam May 26, 2026
3cf3ce9
Merge in WireMod updates to sbncode release branch.
gputnam May 26, 2026
71c4c81
Merge branch 'feature/hhausner_wiremod_xxw-gputnam' of github.com:SBN…
gputnam May 26, 2026
39d4082
Fix operator precedence bug.
gputnam May 26, 2026
b056bbe
Merge branch 'feature/hhausner_wiremod_xxw-gputnam' of github.com:SBN…
gputnam May 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions sbncode/CAFMaker/RecoUtils/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
art_make_library( LIBRARY_NAME caf_RecoUtils
SOURCE RecoUtils.cc
LIBRARIES
sbnanaobj::StandardRecord
art::Framework_Core
art::Framework_Services_Registry
art::Framework_Principal
Expand Down
127 changes: 127 additions & 0 deletions sbncode/HitFinder/BadChannelHitCheck_module.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
////////////////////////////////////////////////////////////////////////
// Class: BadChannelHitCheck
// Plugin Type: analyzer
// File: BadChannelHitCheck_module.cc
//
// Validation analyzer for the GaussHitFinderSBN "ExcludeBadChannels"
// feature. For each configured recob::Hit collection it checks every
// hit's channel against the channel-status database service; if any hit
// sits on a channel the database flags as bad, the art job is failed
// (by throwing). This lets a ctest verify end-to-end that bad channels
// are excluded from the hit finder output.
////////////////////////////////////////////////////////////////////////

#include "art/Framework/Core/EDAnalyzer.h"
#include "art/Framework/Core/ModuleMacros.h"
#include "art/Framework/Principal/Event.h"
#include "art/Framework/Services/Registry/ServiceHandle.h"
#include "canvas/Utilities/Exception.h"
#include "canvas/Utilities/InputTag.h"
#include "fhiclcpp/types/Atom.h"
#include "fhiclcpp/types/Sequence.h"
#include "messagefacility/MessageLogger/MessageLogger.h"

#include "larcoreobj/SimpleTypesAndConstants/RawTypes.h" // raw::ChannelID_t
#include "lardataobj/RecoBase/Hit.h"
#include "larevt/CalibrationDBI/Interface/ChannelStatusService.h"
#include "larevt/CalibrationDBI/Interface/ChannelStatusProvider.h"

#include <vector>

namespace sbn {

class BadChannelHitCheck : public art::EDAnalyzer {
public:
struct Config {
fhicl::Sequence<art::InputTag> HitLabels{
fhicl::Name("HitLabels"),
fhicl::Comment("recob::Hit collections to validate against the bad-channel database")};
fhicl::Atom<bool> RequirePresent{
fhicl::Name("RequirePresent"),
fhicl::Comment("Also fail when a hit lands on a channel the database does not list as present"),
false};
fhicl::Atom<bool> ThrowOnFailure{
fhicl::Name("ThrowOnFailure"),
fhicl::Comment("Throw on the first bad-channel hit; if false, collect and throw in endJob()"),
true};
};
using Parameters = art::EDAnalyzer::Table<Config>;

explicit BadChannelHitCheck(Parameters const& p);

void analyze(art::Event const& e) override;
void endJob() override;

private:
std::vector<art::InputTag> const fHitLabels;
bool const fRequirePresent;
bool const fThrowOnFailure;

unsigned long fNHits{0}; ///< total hits checked
unsigned long fNBad{0}; ///< hits found on bad/not-present channels
bool fReportedStatus{false}; ///< whether the DB bad-channel count was logged
};

//-------------------------------------------------------------------
BadChannelHitCheck::BadChannelHitCheck(Parameters const& p)
: art::EDAnalyzer{p}
, fHitLabels{p().HitLabels()}
, fRequirePresent{p().RequirePresent()}
, fThrowOnFailure{p().ThrowOnFailure()}
{}

//-------------------------------------------------------------------
void BadChannelHitCheck::analyze(art::Event const& e)
{
lariov::ChannelStatusProvider const& chanStatus =
art::ServiceHandle<lariov::ChannelStatusService const>()->GetProvider();

if (!fReportedStatus) {
fReportedStatus = true;
mf::LogInfo("BadChannelHitCheck")
<< "channel-status database reports " << chanStatus.BadChannels().size()
<< " bad and " << chanStatus.NoisyChannels().size() << " noisy channel(s).";
}

for (art::InputTag const& tag : fHitLabels) {
auto const& hits = e.getProduct<std::vector<recob::Hit>>(tag);

for (recob::Hit const& hit : hits) {
raw::ChannelID_t const channel = hit.Channel();
++fNHits;

bool const isBad = chanStatus.IsBad(channel);
bool const isAbsent = fRequirePresent && !chanStatus.IsPresent(channel);
if (!isBad && !isAbsent) continue;

++fNBad;
mf::LogError("BadChannelHitCheck")
<< "recob::Hit on " << (isBad ? "BAD" : "NOT-PRESENT") << " channel " << channel
<< " in product '" << tag.encode() << "', event " << e.id();

if (fThrowOnFailure) {
throw art::Exception(art::errors::LogicError)
<< "BadChannelHitCheck: recob::Hit found on "
<< (isBad ? "bad" : "not-present") << " channel " << channel
<< " (product '" << tag.encode() << "', event " << e.id() << ")\n";
}
}
}
}

//-------------------------------------------------------------------
void BadChannelHitCheck::endJob()
{
mf::LogInfo("BadChannelHitCheck")
<< "Checked " << fNHits << " hit(s); " << fNBad << " on bad/not-present channels.";

if (fNBad > 0) {
throw art::Exception(art::errors::LogicError)
<< "BadChannelHitCheck FAILED: " << fNBad << " of " << fNHits
<< " hit(s) are on bad/not-present channels.\n";
}
}

} // namespace sbn

DEFINE_ART_MODULE(sbn::BadChannelHitCheck)
1 change: 1 addition & 0 deletions sbncode/HitFinder/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ cet_build_plugin(GaussHitFinderSBN art::module
)
cet_build_plugin(ChannelROIToWire art::module LIBRARIES ${MODULE_LIBRARIES})
cet_build_plugin(WireToChannelROI art::module LIBRARIES ${MODULE_LIBRARIES})
cet_build_plugin(BadChannelHitCheck art::module LIBRARIES ${MODULE_LIBRARIES})


install_headers()
Expand Down
2 changes: 1 addition & 1 deletion sbncode/HitFinder/ChannelROIToWire_module.cc
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ void ChannelROIToWire::produce(art::Event& evt)

std::vector<float> dataVec(range.data().size());

for(size_t binIdx = 0; binIdx < range.data().size(); binIdx++) dataVec[binIdx] = std::round(range.data()[binIdx] / ADCScaleFactor);
for(size_t binIdx = 0; binIdx < range.data().size(); binIdx++) dataVec[binIdx] = range.data()[binIdx] / ADCScaleFactor;

ROIVec.add_range(startTick, std::move(dataVec));
}
Expand Down
21 changes: 21 additions & 0 deletions sbncode/HitFinder/GaussHitFinderSBN_module.cc
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
#include "larcoreobj/SimpleTypesAndConstants/RawTypes.h" // raw::ChannelID_t
#include "larreco/HitFinder/HitFilterAlg.h"
#include "lardataobj/RecoBase/Hit.h"
#include "larevt/CalibrationDBI/Interface/ChannelStatusService.h"
#include "larevt/CalibrationDBI/Interface/ChannelStatusProvider.h"

#include "sbnobj/ICARUS/TPC/ChannelROI.h"
#include "sbncode/HitFinder/HitFinderUtilities/HitCreator.h"
Expand Down Expand Up @@ -72,6 +74,7 @@ namespace hit {

const bool fFilterHits;
const bool fFillHists;
const bool fExcludeBadChannels; ///< skip input ChannelROIs on database-flagged bad channels

const std::string fCalDataModuleLabel;
const std::string fAllHitsInstanceName;
Expand Down Expand Up @@ -99,6 +102,9 @@ namespace hit {
//HitFilterAlg implementation is threadsafe.
std::unique_ptr<HitFilterAlg> fHitFilterAlg; ///< algorithm used to filter out noise hits

/// Bad-channel database provider; non-null only when fExcludeBadChannels is true.
const lariov::ChannelStatusProvider* fChannelStatus = nullptr;

//only used when fFillHists is true and in single threaded mode.
TH1F* fFirstChi2;
TH1F* fChi2;
Expand All @@ -111,6 +117,7 @@ namespace hit {
: SharedProducer{pset}
, fFilterHits(pset.get<bool>("FilterHits", false))
, fFillHists(pset.get<bool>("FillHists", false))
, fExcludeBadChannels(pset.get<bool>("ExcludeBadChannels", false))
, fCalDataModuleLabel(pset.get<std::string>("CalDataModuleLabel"))
, fAllHitsInstanceName(pset.get<std::string>("AllHitsInstanceName", ""))
, fLongMaxHitsVec(pset.get<std::vector<int>>("LongMaxHits", std::vector<int>() = {25, 25, 25}))
Expand All @@ -127,6 +134,10 @@ namespace hit {
, fPulseRatioCuts(
pset.get<std::vector<float>>("PulseRatioCuts", std::vector<float>() = {0.35, 0.40, 0.20}))
{
// Cache the bad-channel database provider when channel exclusion is enabled.
if (fExcludeBadChannels)
fChannelStatus = &art::ServiceHandle<lariov::ChannelStatusService const>()->GetProvider();

if (fFillHists && art::Globals::instance()->nthreads() > 1u) {
throw art::Exception(art::errors::Configuration)
<< "Cannot fill histograms when multiple threads configured, please set fFillHists to "
Expand Down Expand Up @@ -223,6 +234,13 @@ namespace hit {

auto const& wireReadoutGeom = art::ServiceHandle<geo::WireReadout const>()->Get();

// When bad-channel exclusion is enabled, snapshot the set of channels the
// status database flags as bad once here (single-threaded). The parallel
// loop below then cheaply skips any input ChannelROI on those channels.
const lariov::ChannelStatusProvider::ChannelSet_t badChannels =
fExcludeBadChannels ? fChannelStatus->BadChannels()
: lariov::ChannelStatusProvider::ChannelSet_t{};

// ###############################################
// ### Making a ptr vector to put on the event ###
// ###############################################
Expand Down Expand Up @@ -295,6 +313,9 @@ namespace hit {

raw::ChannelID_t channel = channelROI->Channel();

// Skip channels flagged as bad in the channel-status database.
if (fExcludeBadChannels && badChannels.count(channel)) return;

// get the WireID for this hit
std::vector<geo::WireID> wids = wireReadoutGeom.ChannelToWire(channel);
// for now, just take the first option returned from ChannelToWire
Expand Down
Loading