Linearize additive systs around param model; add --forceLinear#135
Merged
Conversation
For systematic_type == "normal", the linearized variation rnorm(poi) * norm + theta * logk does not scale with the param-model factor rnorm. A +/-20% variation defined at the MC nominal therefore becomes a different relative effect once rnorm moves away from 1 (e.g. for data-driven background parametrisations like ABCD/SmoothABCD whose POIs are typically far from their default value). Pre-multiply logk by rnorm_init = param_model.compute(xparamdefault) once at fitter construction so the relative size of an additive variation matches the multiplicative case at the linearization point. The scaling is a constant, so the hot path stays strictly linear in theta and no theta*poi bilinearity is introduced. For systematic_type == "log_normal" the existing rnorm * exp(theta*logk) form already has this property, so self.logk / self.logk_csr just alias the original indata tensors and no copy is made. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Force self.is_linear True regardless of the structural checks (chisqFit/covarianceFit, param_model linearity, symmetric tensor, systematic_type, bbstat linearity). The minimize() path then takes a single Cholesky / Hessian-CG step from the current x, i.e. a Gaussian approximation around that point. The user is responsible for ensuring the result is meaningful, typically by wrapping the fit in an outer iteration that re-anchors the linearization point. Also drop the heavyweight 'from rabbit import fitter' import in parsing.py in favor of pulling VALID_BIN_BY_BIN_STAT_TYPES directly from rabbit.bbstat.bbstat, so parsing no longer needs to import the full fitter module. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
systematic_type == \"normal\"with a non-trivial param model (e.g. ABCD / SmoothABCD whose POIs typically sit far from their default), the linearized variationrnorm(poi) * norm + theta * logkdid not naturally scale withrnorm, so a ±20% effect defined at the MC nominal became a different relative effect oncernormmoved away from 1. Nowlogkis pre-multiplied byrnorm_init = param_model.compute(xparamdefault)once at fitter construction. The scaling is a constant so the hot path stays strictly linear intheta(notheta·poibilinearity).log_normalalready had this property, so its tensors are just aliased — no copy.--forceLinearto forceself.is_linear = Trueregardless of the structural checks.minimize()then takes a single Cholesky / Hessian-CG step from the currentx(a Gaussian approximation around that point). Intended for iterative linearized unfolding, where the outer loop re-anchors the linearization point.parsing.py: pullVALID_BIN_BY_BIN_STAT_TYPESdirectly fromrabbit.bbstat.bbstatinstead of importing the fullfittermodule.Test plan
test_tensor.hdf5(log_normal) andtest_tensor_linearized.hdf5(normal) fits still converge to EDM ≈ 1e-16 with no flag.self.logkscales process 0 by 2.5 and leaves other processes untouched when a test param model withxparamdefault=[2.5]is plugged in.--forceLinearemits the info message and takes the Cholesky path ontest_tensor_linearized.hdf5.🤖 Generated with Claude Code