Skip to content

asymmetric traditional impacts; unblinding groups#133

Closed
lucalavezzo wants to merge 11 commits into
WMass:mainfrom
lucalavezzo:luca-dev
Closed

asymmetric traditional impacts; unblinding groups#133
lucalavezzo wants to merge 11 commits into
WMass:mainfrom
lucalavezzo:luca-dev

Conversation

@lucalavezzo

Copy link
Copy Markdown
Collaborator

No description provided.

@lucalavezzo lucalavezzo changed the title asymmetric traditoinal impacts; unblinding groups asymmetric traditional impacts; unblinding groups Apr 30, 2026

@davidwalter2 davidwalter2 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Here are a few comments to start with, please also add coverage for the new features in the CI, the asymmetric impacts but also maybe other things. If it's not too much work maybe break it up in separate PRs

Comment thread bin/rabbit_fit.py
nargs="+",
help="Regex(es) excluding nuisances from --asymImpacts.",
)
parser.add_argument(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I would remove that option and make it default to compute all nuisances with asymImpacts, then exclude the ones you like with --asymImpactsExclude or specify a list with the --asymImpactsInclude otherwise we have too many CLAs

Comment thread bin/rabbit_fit.py
Comment thread bin/rabbit_fit.py
Comment thread bin/rabbit_fit.py
Comment thread bin/rabbit_fit.py
For each selected nuisance, find the asymmetric +/- 1 sigma points on the
Delta(2NLL)=q likelihood contour via constrained minimization (contour_scan).
The shifts of every fitter parameter at those points are the asymmetric
impacts. Group impacts are obtained by quadrature envelope of the contained

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think the convention for grouped impacts in the case of traditional impacts is different, we should use the analogue to what is done in the gaussian case

impacts. Group impacts are obtained by quadrature envelope of the contained
nuisances, separately for the down and up sides.

Nuisances that are structurally symmetric (logkhalfdiff identically zero)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I don't think this is true because nonlinear effects can lead to asymmetric constraints and impacts also for symmetric nuisances. I think by default we should do the most generic and compute for all nuisances and the user has to specify explicitly which he wants to include/exclude

q=1,
contour_xtol=1e-4,
contour_gtol=1e-4,
contour_maxiter=200,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think the default should be set to effectively infinite, 5000 or so, since the user does not expect it to stop early



def _gather_poi_noi_vector(v, noiidxs, nsignal_params=0):
def _gather_poi_noi_vector(v, noiidxs, nsignal_params=0, nmodel_params=None):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Is this computing the impacts also for POUs? If so, why?

Comment thread rabbit/parsing.py
"uncertainty rows; their entries in the output are NaN.",
)
parser.add_argument(
"--paramModelPriors",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think there should be no CLA for that, if the model defines priors they should be applied by default (since naively the user expects the priors to be applied in case he defines them). So either remove the option and leave it to the user to implement something in the model parser, or add the inverse of this option to disable model priors.

lucalavezzo added a commit to lucalavezzo/rabbit that referenced this pull request Jun 12, 2026
Per review on WMass#133 (parsing.py:252): there is no rabbit-side
CLA anymore. If a ParamModel declares prior_sigmas, the priors are
applied; whether and how to enable them (e.g. a token in the
--paramModel spec) is the model's own decision.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
lucalavezzo added a commit to lucalavezzo/rabbit that referenced this pull request Jun 12, 2026
Per review on WMass#133 (asym_impacts.py:7): grouped asymmetric
impacts now follow the traditional grouped-impact convention generalized
to the asymmetric case. Per side, the group impact is
sqrt(delta^T rho_GG^-1 delta) over the group'\''s scanned nuisances, with
rho_GG the postfit correlation submatrix — the exact analogue of
sqrt(v^T C_GG^-1 v) used for symmetric grouped impacts, reducing to it
in the Gaussian limit and to a quadrature sum for uncorrelated
nuisances. Verified on the test tensor that near-Gaussian groups
reproduce the traditional grouped impacts to ~1e-3.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
lucalavezzo added a commit to lucalavezzo/rabbit that referenced this pull request Jun 12, 2026
Reconciles the review discussion on WMass#133 (rabbit_fit.py:603):
when --externalPostfit provides a covariance it is used as before; when
it does not (the fitresult was produced with --noHessian), the Hessian
is recomputed at the loaded postfit point instead of silently writing no
covariance. This enables the two-pass recipe for models whose full
Hessian is infeasible during the fit: pass 1 fits with --noHessian,
pass 2 reruns with --externalPostfit ... --noFit (without --noHessian)
to obtain the covariance. Verified on the test tensor that the two-pass
covariance is identical to the single-pass one, and that a fitresult
with a covariance is still consumed without recomputation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
lucalavezzo added a commit to lucalavezzo/rabbit that referenced this pull request Jun 12, 2026
Per review on WMass#133: param_prior_sigmas / param_prior_means
are stored once as TF constants holding the priors as declared (NaN
where no prior); the compute-safe masked forms are derived inside
_compute_lc, and the output metadata reads the arrays via .numpy().

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@lucalavezzo

Copy link
Copy Markdown
Collaborator Author

Thanks @davidwalter2 for the comments, I've addressed them and split up the PR into 3 more managable ones:

davidwalter2 pushed a commit that referenced this pull request Jun 12, 2026
Per review on #133: drop --asymImpactsAll and
--asymImpactsMaxiter; --asymImpacts now scans every constrained nuisance
by default (nonlinear effects can produce asymmetric impacts even for
structurally symmetric templates) with --asymImpactsInclude/Exclude as
the only gating. The trust-constr maxiter default is raised to 5000 so
scans are not cut off early. The structural-symmetry skip remains
available programmatically. Clarify in traditional_impacts that POUs
only act as impact sources, never as impact rows. Add the
global-asym-impacts test to the CI unit-test matrix.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
lucalavezzo added a commit to lucalavezzo/rabbit that referenced this pull request Jun 12, 2026
Per review on WMass#133 (parsing.py:252): there is no rabbit-side
CLA anymore. If a ParamModel declares prior_sigmas, the priors are
applied; whether and how to enable them (e.g. a token in the
--paramModel spec) is the model's own decision.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
lucalavezzo added a commit to lucalavezzo/rabbit that referenced this pull request Jun 12, 2026
Per review on WMass#133: param_prior_sigmas / param_prior_means
are stored once as TF constants holding the priors as declared (NaN
where no prior); the compute-safe masked forms are derived inside
_compute_lc, and the output metadata reads the arrays via .numpy().

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
davidwalter2 pushed a commit that referenced this pull request Jun 22, 2026
Per review on #133: drop the unnecessary try/except and the
incorrect L-BFGS label (the callback counts iterations of whichever
minimizer method is in use).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
davidwalter2 pushed a commit that referenced this pull request Jun 22, 2026
Per review on #133 ('or not args.noHessian' should be
removed): with --externalPostfit --noFit the covariance is taken from
the loaded fitresult again, as before. The recompute also failed with a
non-positive-definite Hessian on the test tensor's Asimov workflow.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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