Skip to content

mods for final waveform fit pass#4203

Merged
pinkenburg merged 3 commits intosPHENIX-Collaboration:masterfrom
mchiu-bnl:mbd
Mar 3, 2026
Merged

mods for final waveform fit pass#4203
pinkenburg merged 3 commits intosPHENIX-Collaboration:masterfrom
mchiu-bnl:mbd

Conversation

@mchiu-bnl
Copy link
Contributor

@mchiu-bnl mchiu-bnl commented Mar 2, 2026

comment: aborts if calibs don't exist for waveform fits, added info on waveform fit to RawHit output object, added refits to waveforms to check for better alternative fit

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work for users)
  • Requiring change in macros repository (Please provide links to the macros pull request in the last section)
  • I am a member of GitHub organization of sPHENIX Collaboration, EIC, or ECCE (contact Chris Pinkenburg to join)

What kind of change does this PR introduce? (Bug fix, feature, ...)

TODOs (if applicable)

Links to other PRs in macros and calibration repositories (if applicable)

Motivation and Context

This PR improves MBD (Minimum Bias Detector) waveform reconstruction and data output to support a production waveform-fit pass: it enforces required calibration availability, records detailed fit-quality information with raw hits, and implements more robust/refit-capable waveform fitting to improve signal extraction and allow downstream validation.

Key Changes

  • Data model / IO

    • Introduces V2 container/hit classes: MbdRawContainerV2, MbdRawHitV2, with ROOT LinkDef/dictionary support and public headers/sources added.
    • Extends base MbdRawHit with virtual accessors/mutators for chi2/ndf and fit-info: get_chi2ndf(), set_chi2ndf(), get_fitinfo(), set_fitinfo().
    • Adds MBD_INVALID_USHORT sentinel in MbdReturnCodes.h for new fields.
    • Updates MbdReco to create MbdRawContainerV2 (V2 becomes the primary output container).
  • Calibration & workflow control

    • MbdCalib reorders/strengthens calibration loading: Status is loaded earlier if local MBD_CALDIR is absent; QFIT, TT_T0, TQ_T0, and T0CORR loading are more explicitly gated by the _fitsonly flag to enforce required calibrations for waveform-fit passes.
    • Workflow now aborts when required calibrations for waveform fits are missing (abort condition tied to _fitsonly/production fit mode).
  • Event handling & output population

    • MbdEvent propagates event sequence (evtseq) from GL1/PRDF paths into per-channel MbdSig objects (SetEvtNum) and preserves event sequencing across online/offline paths.
    • Raw hit outputs now include per-PMT fit metrics: chi2/ndf and fitinfo are appended to output containers for each PMT.
  • Waveform fitting algorithm and diagnostics

    • MbdSig: replaces legacy Gaussian tail with a new SignalTail model and introduces richer fit logic with multiple fit modes (f_fitmode), saturation-aware refits, two-template fits, candidate selection based on chi2/ndf, and PrintResiduals diagnostic tooling.
    • Adds accessors to expose fit metrics: SetEvtNum(), GetChi2(), GetNDF(), GetChi2NDF(), GetFitInfo().
    • Adds refit strategy to attempt alternative fits and select the best solution.
  • Miscellaneous

    • Minor cleanup (reduced debug prints) and housekeeping (dictionary/linkdef files, container Reset/identify/clock APIs).

Potential Risk Areas

  • IO format / compatibility (High)

    • Introduction of V2 classes changes on-disk/ROOT serialization; downstream consumers must support V2 or migration will be required.
    • New per-hit fields increase payload; storage and transfer implications should be evaluated.
  • Reconstruction behavior & physics validation (High)

    • New tail model, multi-template fits, and refit selection will change reconstructed ADC/TTDC/TQDC and timing/energy estimates. Thorough validation vs. reference simulation/data is required.
    • Calibration gating behind _fitsonly can change behavior of non-fit passes if flags/configuration differ.
  • Build / runtime (Medium)

    • Added ROOT dictionaries and LinkDef files increase build surface; dictionary mismatches may cause serialization/runtime issues.
    • MbdReco now instantiates V2 containers — ensure all nodes and consumers are updated.
  • Performance & thread-safety (Medium)

    • More complex fitting with refits and candidate evaluation increases CPU cost; high-occupancy runs may experience slower reconstruction.
    • No explicit thread-safety analyses added; ensure fitting code and any shared resources (e.g., TF1/fit objects) are safe under multi-threaded reconstruction.

Possible Future Improvements

  • Define and publish a V1→V2 migration/deprecation plan and provide conversion utilities for archived data.
  • Add automated validation tests comparing V1 vs V2 reconstruction, and evaluate physics-level metrics (timing, charge, occupancy).
  • Profile and optimize fit/refit paths; add fast-paths for saturated/unambiguous cases.
  • Document f_fitmode/fitinfo bit-packing and chi2ndf encoding so downstream analysis can reliably interpret fields.
  • Consider exposing a configurable limit on refit attempts or a mode to trade quality for CPU in large-scale production.

Note: This summary was generated with AI assistance and may contain errors or omissions; please review the changed files directly (MbdSig*, MbdEvent*, MbdCalib*, MbdRawHit*/ContainerV2*, Makefile.am, LinkDefs) and verify calibration/IO implications before merging.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 2, 2026

📝 Walkthrough

Walkthrough

Adds MBD V2 data types and ROOT dictionaries, migrates reconstruction to use MbdRawContainerV2, extends hit/container APIs for event/clock/fit metadata, reorders calibration loading, propagates event sequence into signals, and significantly refines waveform fitting with chi2/fitinfo recording and tail-based fitting.

Changes

Cohort / File(s) Summary
V2 types & dictionaries
offline/packages/mbd/MbdRawContainerV2.h, offline/packages/mbd/MbdRawContainerV2.cc, offline/packages/mbd/MbdRawContainerV2LinkDef.h, offline/packages/mbd/MbdRawHitV2.h, offline/packages/mbd/MbdRawHitV2.cc, offline/packages/mbd/MbdRawHitV2LinkDef.h
Adds new MbdRawContainerV2 and MbdRawHitV2 classes, TClonesArray storage, event/clock accessors, chi2/fitinfo packing, Reset/identify, and ROOT LinkDef entries for dictionary generation.
Build files
offline/packages/mbd/Makefile.am
Adds V2 headers, sources, and ROOTDICT entries for both online and offline build targets; integrates V2 dicts alongside V1.
Base APIs & constants
offline/packages/mbd/MbdRawHit.h, offline/packages/mbd/MbdReturnCodes.h
Introduces virtual get/set chi2ndf and fitinfo in MbdRawHit; adds MBD_INVALID_USHORT constant.
Reconstruction migration
offline/packages/mbd/MbdReco.cc
Switches node creation to instantiate MbdRawContainerV2 and updates include.
Event processing updates
offline/packages/mbd/MbdEvent.cc
Propagates event sequence into MbdSig via SetEvtNum in both online/offline paths; records chi2ndf and fitinfo into per-PMT output containers; tightens InitRun abort to require _fitsonly.
Calibration control flow
offline/packages/mbd/MbdCalib.cc
Reorders calibration loading when MBD_CALDIR is absent: Status now loaded earlier; QFIT/TT_T0/TQ_T0 downloads gated more explicitly by _fitsonly.
Signal fitting & diagnostics
offline/packages/mbd/MbdSig.h, offline/packages/mbd/MbdSig.cc
Adds SignalTail() and PrintResiduals(); replaces Gaussian ped_tail with tail-based pileup model; introduces f_fitmode, SetEvtNum, richer two-template/saturation-aware fit logic, chi2/ndf tracking, and verbose residual diagnostics.
Minor & housekeeping
offline/packages/mbd/MbdRawHitV1.cc, offline/packages/mbd/MbdRawContainerV2LinkDef.h
Removes a debug print in V1 Clear; adds small LinkDef and dictionary scaffolding for V2.

Possibly related PRs


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 11


ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 90cd02f and 6e6503f.

📒 Files selected for processing (14)
  • offline/packages/mbd/Makefile.am
  • offline/packages/mbd/MbdCalib.cc
  • offline/packages/mbd/MbdEvent.cc
  • offline/packages/mbd/MbdRawContainerV2.cc
  • offline/packages/mbd/MbdRawContainerV2.h
  • offline/packages/mbd/MbdRawContainerV2LinkDef.h
  • offline/packages/mbd/MbdRawHit.h
  • offline/packages/mbd/MbdRawHitV2.cc
  • offline/packages/mbd/MbdRawHitV2.h
  • offline/packages/mbd/MbdRawHitV2LinkDef.h
  • offline/packages/mbd/MbdReco.cc
  • offline/packages/mbd/MbdReturnCodes.h
  • offline/packages/mbd/MbdSig.cc
  • offline/packages/mbd/MbdSig.h

Comment on lines +53 to +60
void set_npmt(const Short_t ival) override
{
npmt = ival;
return;
}

/// get Number of Mbd Pmt's
Short_t get_npmt() const override { return MbdRawHits->GetEntries(); }
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Inconsistent set_npmt/get_npmt behavior — potential API confusion.

set_npmt() assigns to the private member npmt, but get_npmt() returns MbdRawHits->GetEntries(). This means:

  • set_npmt(128) followed by get_npmt() will not return 128 unless the TClonesArray also happens to have 128 entries.
  • isValid() checks npmt, but users calling get_npmt() see a different value.

Consider aligning these: either have get_npmt() return the npmt member, or document the semantic difference clearly. This matches V1's pattern, so if intentional, please add a clarifying comment.

Option A: Return the stored member
-  Short_t get_npmt() const override { return MbdRawHits->GetEntries(); }
+  Short_t get_npmt() const override { return npmt; }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
void set_npmt(const Short_t ival) override
{
npmt = ival;
return;
}
/// get Number of Mbd Pmt's
Short_t get_npmt() const override { return MbdRawHits->GetEntries(); }
void set_npmt(const Short_t ival) override
{
npmt = ival;
return;
}
/// get Number of Mbd Pmt's
Short_t get_npmt() const override { return npmt; }

Comment on lines +43 to +68
virtual Float_t get_chi2ndf() const
{
PHOOL_VIRTUAL_WARNING;
return MbdReturnCodes::MBD_INVALID_FLOAT;
}

virtual UShort_t get_fitinfo() const
{
PHOOL_VIRTUAL_WARNING;
return 0;
}

virtual void set_pmt(const Short_t /*pmt*/, const Float_t /*adc*/, const Float_t /*ttdc*/, const Float_t /*qtdc*/)
{
PHOOL_VIRTUAL_WARNING;
}

virtual void set_chi2ndf(const Double_t /*chi2ndf*/)
{
PHOOL_VIRTUAL_WARNING;
}

virtual void set_fitinfo(const UShort_t /*fitinfo*/)
{
PHOOL_VIRTUAL_WARNING;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Document ABI/downstream impact of the MbdRawHit interface expansion.

Lines 43-68 add new virtual methods on public base class MbdRawHit, which changes the vtable surface. Please include compatibility notes (downstream rebuild expectations and migration impact) in the PR/release notes.

As per coding guidelines: "If interfaces change, ask for compatibility notes and any needed downstream updates."

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

♻️ Duplicate comments (3)
offline/packages/mbd/MbdRawHitV2.h (1)

13-14: ⚠️ Potential issue | 🟠 Major

Initialize members in-class to avoid undefined reads before Clear().

Line 13 default-constructs the object, but Line 80–84 members are uninitialized. Then Line 58 and Line 65 do read-modify-write on fitstat, and Line 75 can read bttdc before initialization. This can produce undefined behavior if Clear() is not called first.

Proposed fix
 private:
-  Short_t  bpmt;
-  UShort_t fitstat; //waveform fit status
-  Float_t  badc;
-  Float_t  bttdc;
-  Float_t  bqtdc;
+  Short_t  bpmt{-1};
+  UShort_t fitstat{0}; // waveform fit status
+  Float_t  badc{std::numeric_limits<Float_t>::quiet_NaN()};
+  Float_t  bttdc{std::numeric_limits<Float_t>::quiet_NaN()};
+  Float_t  bqtdc{std::numeric_limits<Float_t>::quiet_NaN()};

Also applies to: 58-59, 65-65, 73-76, 80-84

offline/packages/mbd/MbdSig.cc (2)

702-704: ⚠️ Potential issue | 🟠 Major

Guard pedestal fit ratio decisions when NDF <= 0.

ndf is captured at Lines 703–704, but Line 726 still uses chi2/ndf unguarded (and Line 717 in verbose mode does the same). This can produce inf/NaN and flip pedestal classification.

Proposed fix
   double chi2 = ped_fcn->GetChisquare();
   double ndf = ped_fcn->GetNDF();
+  const double chi2ndf = (ndf > 0.) ? (chi2 / ndf) : std::numeric_limits<double>::infinity();
@@
-    double chi2ndf = ped_fcn->GetChisquare()/ped_fcn->GetNDF();
+    const double v_ndf = ped_fcn->GetNDF();
+    const double chi2ndf = (v_ndf > 0.) ? (ped_fcn->GetChisquare() / v_ndf) : std::numeric_limits<double>::infinity();
@@
-  if ( chi2/ndf < 4.0 )
+  if ( chi2ndf < 4.0 )

1457-1465: ⚠️ Potential issue | 🟠 Major

FitTemplate still allows invalid chi2/NDF comparisons on zero NDF.

newchi2ndf defaults to 0. when newndf <= 0 (Lines 1457–1461), which can incorrectly treat an invalid fit as better. Also, Line 1527 compares two unguarded ratios that may divide by zero.

Proposed fix
-    Double_t newchi2ndf = 0.;
-    if ( newndf>0.) 
-    {
-      newchi2ndf = newchi2/newndf;
-    }
+    Double_t newchi2ndf = std::numeric_limits<double>::infinity();
+    if (newndf > 0.)
+    {
+      newchi2ndf = newchi2 / newndf;
+    }
@@
-  if ( (newchi2/newndf)<f_chi2/f_ndf )
+  const Double_t oldchi2ndf = (f_ndf > 0.) ? (f_chi2 / f_ndf) : std::numeric_limits<double>::infinity();
+  const Double_t sat_newchi2ndf = (newndf > 0.) ? (newchi2 / newndf) : std::numeric_limits<double>::infinity();
+  if (sat_newchi2ndf < oldchi2ndf)

Also applies to: 1525-1528


ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6e6503f and 979697c.

📒 Files selected for processing (6)
  • offline/packages/mbd/MbdRawContainerV2.h
  • offline/packages/mbd/MbdRawHitV1.cc
  • offline/packages/mbd/MbdRawHitV2.cc
  • offline/packages/mbd/MbdRawHitV2.h
  • offline/packages/mbd/MbdSig.cc
  • offline/packages/mbd/MbdSig.h
🚧 Files skipped from review as they are similar to previous changes (2)
  • offline/packages/mbd/MbdRawHitV2.cc
  • offline/packages/mbd/MbdRawContainerV2.h

Comment on lines +1248 to +1254
// fitmode:
// 0 - no info or no fit
// 1 - regular template fit (shortened)
// 2 - two template fit
// 3 - two template fit, neg ampl 2nd template
// 4 - saturated template fit
// 5 - saturated and shortened template fit
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

f_fitmode code 3 semantics are inconsistent with assignment logic.

The fitmode comment says code 3 means “two template fit, neg ampl 2nd template,” but Line 1464’s rejection condition sets f_fitmode = 3 for several unrelated reasons (time2>15, ampl1<0, or newchi2ndf>chi2ndf). Since fitinfo is now exported, this mislabels downstream metadata.

Also applies to: 1464-1472

@sphenix-jenkins-ci
Copy link

Build & test report

Report for commit 6e6503f5c5261d3b311e0464287d2133361c2d98:
Jenkins passed


Automatically generated by sPHENIX Jenkins continuous integration
sPHENIX             jenkins.io

@sphenix-jenkins-ci
Copy link

Build & test report

Report for commit 979697c730795d74b7f32641729e9562e4d43f57:
Jenkins passed


Automatically generated by sPHENIX Jenkins continuous integration
sPHENIX             jenkins.io

@pinkenburg pinkenburg merged commit 7ef781f into sPHENIX-Collaboration:master Mar 3, 2026
22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants