Skip to content

SBND Timing Reconstruction Refactor#915

Open
VCLanNguyen wants to merge 54 commits intodevelopfrom
feature/frame_shift_refactor_v10_14_02
Open

SBND Timing Reconstruction Refactor#915
VCLanNguyen wants to merge 54 commits intodevelopfrom
feature/frame_shift_refactor_v10_14_02

Conversation

@VCLanNguyen
Copy link
Copy Markdown
Contributor

@VCLanNguyen VCLanNguyen commented Feb 14, 2026

Description

  • Timing reconstruction is refactored in this PR, affecting the decode/reconstruction workflow of CRT/PMT/XA.
  • After the refactoring, the @FrameShiftModule@ runs first in the decode chain, outputs timing products to be used at PMT/XA decoder and CRTStrip reconstruction.
  • Relevant PMT reconstruction modules at Reco1/Reco2 are updated.
  • The timing correction applied at CAFMakeer is undone. - The timing correction applied at CAFMakeer is undone. This should ressolve this issue: Converge timing correction in CAFMaker for SBND and ICARUS sbncode#567
  • Details and validation plots can before in the linked docdb.

Link(s) to docdb describing changes (optional)

https://sbn-docdb.fnal.gov/cgi-bin/sso/ShowDocument?docid=46654

Relevant PR links (optional)

This PR needs the XA decoder PR in sbndcode to go in first:
#847

This PR needs to be merged together with this group of PRs:

Checklist

  • Added at least 1 label from available labels.
  • Assigned at least 1 reviewer under Reviewers,
  • Assigned all contributers including yourself under Assignees
  • Linked any relevant issues under Developement
  • Does this PR affect CAF data format? If so, please assign a CAF maintainer (PetrilloAtWork or JosiePaton) as additional reviewer.
  • Does this affect the standard workflow?
  • Is this PR a patch for the ongoing production? If so, separate PR must also be made for production/v10_06_00 branch!

aliciavr and others added 30 commits October 9, 2025 04:05
@VCLanNguyen VCLanNguyen added crt Cosmic Ray Tagger breaking change pds Photon Detection System caf Common analysis framework data features for data processing labels Mar 4, 2026
@VCLanNguyen VCLanNguyen changed the title Feature/frame shift refactor v10 14 02 Timing Reconstruction Refactor Mar 4, 2026
@VCLanNguyen VCLanNguyen changed the title Timing Reconstruction Refactor SBND Timing Reconstruction Refactor Mar 4, 2026
@VCLanNguyen VCLanNguyen marked this pull request as ready for review March 4, 2026 01:49
@aantonakis
Copy link
Copy Markdown
Contributor

crt veto looks good

Copy link
Copy Markdown
Contributor

@lynnt20 lynnt20 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

approved for PMT side!

Copy link
Copy Markdown
Contributor

@aliciavr aliciavr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All good on XA's side!

@VCLanNguyen VCLanNguyen requested a review from JosiePaton April 20, 2026 19:37
@VCLanNguyen
Copy link
Copy Markdown
Contributor Author

@JosiePaton @PetrilloAtWork can you guys review for CAF?

Copy link
Copy Markdown
Member

@PetrilloAtWork PetrilloAtWork left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some changes suggested here and there as usual, plus:

  1. something that looks like a bug (which must be fixed, hence the rejection)
  2. a questionable implementation of the difference of timestamps

A reiterated comment/recommendation: please format all the relevant comments on the usage of the functions and data member to Doxygen format.

Comment on lines +122 to +126
art::Handle<sbnd::timing::FrameShiftInfo> frameShiftHandle;
e.getByLabel(fFrameShiftModuleLabel, frameShiftHandle);

if(DAQHeaderHandle.isValid())
{
artdaq::RawEvent rawHeaderEvent = artdaq::RawEvent(*DAQHeaderHandle);
raw_ts = rawHeaderEvent.timestamp() - fRawTSCorrection;
}
if(!frameShiftHandle.isValid())
throw std::runtime_error("Frame Shift Info object is invalid, check data quality");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the handle is only used to access its data, a more compact expression is:

Suggested change
art::Handle<sbnd::timing::FrameShiftInfo> frameShiftHandle;
e.getByLabel(fFrameShiftModuleLabel, frameShiftHandle);
if(DAQHeaderHandle.isValid())
{
artdaq::RawEvent rawHeaderEvent = artdaq::RawEvent(*DAQHeaderHandle);
raw_ts = rawHeaderEvent.timestamp() - fRawTSCorrection;
}
if(!frameShiftHandle.isValid())
throw std::runtime_error("Frame Shift Info object is invalid, check data quality");
auto const & frameShift
= e.getProduct<sbnd::timing::FrameShiftInfo> (fFrameShiftModuleLabel);

that also throws an exception in case of failure; note that you lose control on the exception message though. Since art::Event::getByLabel() return the status of the operation, another alternative is:

Suggested change
art::Handle<sbnd::timing::FrameShiftInfo> frameShiftHandle;
e.getByLabel(fFrameShiftModuleLabel, frameShiftHandle);
if(DAQHeaderHandle.isValid())
{
artdaq::RawEvent rawHeaderEvent = artdaq::RawEvent(*DAQHeaderHandle);
raw_ts = rawHeaderEvent.timestamp() - fRawTSCorrection;
}
if(!frameShiftHandle.isValid())
throw std::runtime_error("Frame Shift Info object is invalid, check data quality");
art::Handle<sbnd::timing::FrameShiftInfo> frameShiftHandle;
if (!e.getByLabel(fFrameShiftModuleLabel, frameShiftHandle))
throw std::runtime_error("Frame Shift Info object is invalid, check data quality");

Comment on lines +137 to +140
{
std::set<uint32_t> unix_set = UnixSet(FEBDataVec);
ref_time_s = unix_set.size() ? *unix_set.rbegin(): 0;
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please fix the indentation (I suppose tabulate characters are mixed in).


if(unix_diff < -1 || unix_diff > 1)
{
throw std::runtime_error(Form("Unix timestamps differ by more than 1 (%li)", unix_diff));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without pulling in ROOT's Form():

Suggested change
throw std::runtime_error(Form("Unix timestamps differ by more than 1 (%li)", unix_diff));
throw std::runtime_error("Unix timestamps differ by more than 1 (" + std::to_string(unix_diff) + ")");

std::to_string() is defined in the C++ standard header string.

Comment on lines +226 to +232
if(unix_diff == 1)
t0_etrig -= 1e9;
else if(unix_diff == -1)
t0_etrig += 1e9;

if(t0_etrig < fETrigMin || t0_etrig > fETrigMax)
return stripHits;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix the code indentation:

Suggested change
if(unix_diff == 1)
t0_etrig -= 1e9;
else if(unix_diff == -1)
t0_etrig += 1e9;
if(t0_etrig < fETrigMin || t0_etrig > fETrigMax)
return stripHits;
if(unix_diff == 1)
t0_etrig -= 1e9;
else if(unix_diff == -1)
t0_etrig += 1e9;
if(t0_etrig < fETrigMin || t0_etrig > fETrigMax)
return stripHits;

art::ServiceHandle<SBND::CRTChannelMapService> fCRTChannelMapService;

std::string fFEBDataModuleLabel;
std::string fFrameShiftModuleLabel;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that the appropriate type is art::InputTag, not std::string.
Historically the latter was used because fhicl::ParameterSet::get<art::InputTag>() was broken; that time is long gone.
Not necessarily recommending the change here, unless you change all the tag data members.

private:

// FCL Parameters
std::string fDAQHeaderModuleLabel; // Instance label for DAQ header product
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Turn the comments into Doxygen format, so that they are rendered in the documentation. For example:

Suggested change
std::string fDAQHeaderModuleLabel; // Instance label for DAQ header product
std::string fDAQHeaderModuleLabel; ///< Instance label for DAQ header product

Comment on lines +375 to 384
art::Handle<sbnd::timing::FrameShiftInfo> frameShiftHandle;
e.getByLabel(fFrameShiftLabel, frameShiftHandle);

if (!timingRefHandle.isValid()){
throw cet::exception("WaveformAlignment") << "No raw::TimingReferenceInfo found w/ tag " << fTimingRefLabel << ". Check data quality!";
if (!frameShiftHandle.isValid()){
throw cet::exception("WaveformAlignment") << "No sbnd::timing::FrameShiftInfo found w/ tag " << fFrameShiftLabel << ". Check data quality!";
}
else{
raw::TimingReferenceInfo const& pmt_timing(*timingRefHandle);

_pmt_timing_type = pmt_timing.timingType;
_pmt_timing_ch = pmt_timing.timingChannel;

if (fDebugTimeRef){
std::cout << "Timing Reference For Decoding PMT" << std::endl;
std::cout << " Type = " << _pmt_timing_type << " (SPECTDC = 0; PTB HLT = 1; CAEN-only = 3)." << std::endl;
std::cout << " Channel = " << _pmt_timing_ch << " (TDC ETRIG = 4; PTB BNB Beam+Light = 2)." << std::endl;
}
_frameDefault = frameShiftHandle->FrameDefault();
_pmt_timing_type = frameShiftHandle->TimingTypeDefault();
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest:

Suggested change
art::Handle<sbnd::timing::FrameShiftInfo> frameShiftHandle;
e.getByLabel(fFrameShiftLabel, frameShiftHandle);
if (!timingRefHandle.isValid()){
throw cet::exception("WaveformAlignment") << "No raw::TimingReferenceInfo found w/ tag " << fTimingRefLabel << ". Check data quality!";
if (!frameShiftHandle.isValid()){
throw cet::exception("WaveformAlignment") << "No sbnd::timing::FrameShiftInfo found w/ tag " << fFrameShiftLabel << ". Check data quality!";
}
else{
raw::TimingReferenceInfo const& pmt_timing(*timingRefHandle);
_pmt_timing_type = pmt_timing.timingType;
_pmt_timing_ch = pmt_timing.timingChannel;
if (fDebugTimeRef){
std::cout << "Timing Reference For Decoding PMT" << std::endl;
std::cout << " Type = " << _pmt_timing_type << " (SPECTDC = 0; PTB HLT = 1; CAEN-only = 3)." << std::endl;
std::cout << " Channel = " << _pmt_timing_ch << " (TDC ETRIG = 4; PTB BNB Beam+Light = 2)." << std::endl;
}
_frameDefault = frameShiftHandle->FrameDefault();
_pmt_timing_type = frameShiftHandle->TimingTypeDefault();
}
auto const& frameShift = e.getProduct<sbnd::timing::FrameShiftInfo>(fFrameShiftLabel);
_frameDefault = frameShift.FrameDefault();
_pmt_timing_type = frameShift.TimingTypeDefault();

or, if control on the exception message is desired,

Suggested change
art::Handle<sbnd::timing::FrameShiftInfo> frameShiftHandle;
e.getByLabel(fFrameShiftLabel, frameShiftHandle);
if (!timingRefHandle.isValid()){
throw cet::exception("WaveformAlignment") << "No raw::TimingReferenceInfo found w/ tag " << fTimingRefLabel << ". Check data quality!";
if (!frameShiftHandle.isValid()){
throw cet::exception("WaveformAlignment") << "No sbnd::timing::FrameShiftInfo found w/ tag " << fFrameShiftLabel << ". Check data quality!";
}
else{
raw::TimingReferenceInfo const& pmt_timing(*timingRefHandle);
_pmt_timing_type = pmt_timing.timingType;
_pmt_timing_ch = pmt_timing.timingChannel;
if (fDebugTimeRef){
std::cout << "Timing Reference For Decoding PMT" << std::endl;
std::cout << " Type = " << _pmt_timing_type << " (SPECTDC = 0; PTB HLT = 1; CAEN-only = 3)." << std::endl;
std::cout << " Channel = " << _pmt_timing_ch << " (TDC ETRIG = 4; PTB BNB Beam+Light = 2)." << std::endl;
}
_frameDefault = frameShiftHandle->FrameDefault();
_pmt_timing_type = frameShiftHandle->TimingTypeDefault();
}
try {
auto const& frameShift = e.getProduct<sbnd::timing::FrameShiftInfo>(fFrameShiftLabel);
_frameDefault = frameShift.FrameDefault();
_pmt_timing_type = frameShift.TimingTypeDefault();
}
catch(art::Exception const&) {
throw cet::exception("WaveformAlignment") << "No sbnd::timing::FrameShiftInfo found w/ tag " << fFrameShiftLabel << ". Check data quality!";
}

art_dictionary(DICTIONARY_LIBRARIES
lardataobj::RawData)
art_make_library(
SOURCE TimingUtils.cc
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is redundant. Any reason to specify it?

Suggested change
SOURCE TimingUtils.cc

//Subtract two timestamps in UTC format
//ts1 and ts2 are in nanoseconds in uint64_t format
//Return the difference in nanoseconds as double
double SubtractUTCTimestmap(const uint64_t& ts1, const uint64_t& ts2);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as somewhere earlier:

Suggested change
double SubtractUTCTimestmap(const uint64_t& ts1, const uint64_t& ts2);
double SubtractUTCTimestmap(uint64_t ts1, uint64_t ts2);


//Subtract two timestamps in UTC format
//ts1 and ts2 are in nanoseconds in uint64_t format
//Return the difference in nanoseconds as double
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may be useful to explicitly say which sign that difference has:

Suggested change
//Return the difference in nanoseconds as double
//Return the difference `ts1 - ts2` in nanoseconds as double

Also, please convert this comment into Doxygen format.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking change caf Common analysis framework crt Cosmic Ray Tagger data features for data processing pds Photon Detection System

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants