Skip to content

light yield fix for Run-2 - #917

Open
mvicenzi wants to merge 7 commits into
feature/pmtsim_gainfrom
feature/mv_lightfix
Open

light yield fix for Run-2 #917
mvicenzi wants to merge 7 commits into
feature/pmtsim_gainfrom
feature/mv_lightfix

Conversation

@mvicenzi

Copy link
Copy Markdown
Member

Note : This is being opened against feature/pmtsim_gain to showcase meaningful differences for review, but it should be rebased on the production branch once #892 is merged.

This PR introduces two empirical/effective corrections that close the light model discrepancy for Run-2 by fixing both the signal shape and the overall PE normalization (see SBN-docdb-48157, SBN-docdb-48511).

Two corrections are introduced:

  • ApplyTailSuppression() applies a subtractive, causal correction to the final waveform. It tracks a running low-pass-filtered estimate Q of the waveform (filter with time constant Tau) — and subtracts Eps x Q from each sample (clamped so the pulse cannot flip polarity). Esp is a factor that controls the strenght of the correction. This removes the excess integrated charge in the tail while leaving the prompt peak essentially untouched.

  • Distance-dependent photon survival probability: instead of a flat QE cut, each scintillation photon is now kept with probability QE x S(d), where S(d) is a function of the distance between the emission point of the photon and the PMT. It is configured via specifying distance bins via DistanceSurvival.BinEdges and the corresponding values with DistanceSurvival.Factors. It defaults to 1 outside the configured bin range.

Both corrections are currenlty enabled and tuned ONLY for Run-2 data.
The tune for Run-3/4 is still being optimized.

@mvicenzi mvicenzi self-assigned this Jul 28, 2026
@mvicenzi mvicenzi added the enhancement New feature or request label Jul 28, 2026
This was linked to issues Jul 28, 2026

@PetrilloAtWork PetrilloAtWork left a comment

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 left some minor comments.
This is a configuration-breaking change, and I mentioned a way not to make it so.
However, this PR is very well written and very well documented.

Comment on lines +308 to +310
geo::Point_t const PMTcenter = applySd
? fParams.wireReadoutGeom->OpDetGeoFromOpChannel(channel).GetCenter()
: geo::Point_t{};

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 would argue that, provided that wireReadoutGeom is available, this PMTcenter is better unconditionally set rather than leaving it with a potentially dangerous value { 0, 0, 0 }:

Suggested change
geo::Point_t const PMTcenter = applySd
? fParams.wireReadoutGeom->OpDetGeoFromOpChannel(channel).GetCenter()
: geo::Point_t{};
geo::Point_t const PMTcenter = fParams.wireReadoutGeom->OpDetGeoFromOpChannel(channel).GetCenter();

Comment on lines 1517 to +1520
;

out << '\n' << indent << "Tail suppression: "
<< std::boolalpha << fParams.tailSuppression.apply;

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.

You can also merge this with the previous block:

Suggested change
;
out << '\n' << indent << "Tail suppression: "
<< std::boolalpha << fParams.tailSuppression.apply;
<< '\n' << indent << "Tail suppression: "
<< std::boolalpha << fParams.tailSuppression.apply
;

Just saying.

//
fBaseConfig.distanceSurvival.apply = config.DistanceSurvival().Apply();
fBaseConfig.distanceSurvival.binEdges = config.DistanceSurvival().BinEdges();
fBaseConfig.distanceSurvival.factors = config.DistanceSurvival().Factors();

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.

As written, this PR is a configuration-breaking change.
Given that the configuration structures have sensible defaults, you may consider to make the new configuration tables optional (fhicl::OptionalTable()) and here you can go conditional:

Suggested change
fBaseConfig.distanceSurvival.factors = config.DistanceSurvival().Factors();
//
// tail suppression
//
if (config.TailSuppression()) {
fBaseConfig.tailSuppression.apply = config.TailSuppression()->Apply();
fBaseConfig.tailSuppression.epsilon = config.TailSuppression()->Epsilon();
fBaseConfig.tailSuppression.tau = config.TailSuppression()->Tau();
}
//
// distance-dependent photon survival
//
if (config.DistanceSurvival()) {
fBaseConfig.distanceSurvival.apply = config.DistanceSurvival()->Apply();
fBaseConfig.distanceSurvival.binEdges = config.DistanceSurvival()->BinEdges();
fBaseConfig.distanceSurvival.factors = config.DistanceSurvival()->Factors();
}

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

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Light Fix ICARUS PMT Response Mismatch Between Data and MC

2 participants