From 283fa06a5c3fed3a14123d9581e30aa1fb6af43f Mon Sep 17 00:00:00 2001 From: Luca Lavezzo Date: Tue, 21 Jul 2026 13:38:08 -0400 Subject: [PATCH 1/2] setupRabbit: expose empty-bin systematic clipping/zeroing Add two opt-in CLI flags (both off by default) that forward to the rabbit TensorWriter knobs of the same name: - --clipSystVariations X: clip each bin's log_normal up/down factor to [1/X, X]. - --zeroSystLowNeff X (+ --zeroSystLowNeffProcs): zero every systematic's logk in any (bin, process) with n_eff = sumw^2/sumw2 < X. Tames the ~1e15-1e20 blow-ups from mixed-sign NLO weight-cancellation-residual bins in thin backgrounds (Ztautau/PhotonInduced/Other) that break debug/plot tools. The new knobs are forwarded to TensorWriter only when actually set, so this script remains compatible with rabbit versions predating them. Using the flags requires a rabbit with these TensorWriter arguments (WMass/rabbit#146). Co-Authored-By: Claude Opus 4.8 --- scripts/rabbit/setupRabbit.py | 44 ++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/scripts/rabbit/setupRabbit.py b/scripts/rabbit/setupRabbit.py index 88a3fc3f5..0d7a0d526 100644 --- a/scripts/rabbit/setupRabbit.py +++ b/scripts/rabbit/setupRabbit.py @@ -1095,6 +1095,38 @@ def make_parser(parser=None, argv=None): default="log_normal", help="probability density for systematic variations", ) + parser.add_argument( + "--clipSystVariations", + type=float, + default=0.0, + help="If >0, clip log_normal systematic variations so each bin's up/down " + "factor stays within [1/x, x] (e.g. 10 => [0.1x, 10x]). Tames spurious " + "huge variations in statistically-empty bins (e.g. Ztautau cancellation " + "residuals). 0 disables (default). Keep looser than any genuine lnN " + "(e.g. the 2x photon-induced norm) so real uncertainties are untouched.", + ) + parser.add_argument( + "--zeroSystLowNeff", + type=float, + default=0.0, + help="If >0, zero every systematic's logk in any (bin, process) whose " + "effective sample size n_eff = sumw^2/sumw2 is below this threshold " + "(units of effective events; n_eff is scale-invariant). Such bins are " + "mixed-sign NLO-weight cancellation residuals where logk is noise and " + "nom*exp(logk) blows up. Keeps the nominal, removes only the meaningless " + "systematic lever. 1.0 ('fewer than one effective event') is the " + "recommended value. 0 disables (default). Cleaner than --clipSystVariations " + "(the card itself comes out clean for debug/plot tools).", + ) + parser.add_argument( + "--zeroSystLowNeffProcs", + nargs="+", + default=None, + metavar="PROCESS", + help="Restrict --zeroSystLowNeff to these process names. Default: all " + "processes (safe: only statistically-empty bins are touched, and " + "signal/Zmumu have none).", + ) parser.add_argument( "--presel", nargs=3, @@ -3366,12 +3398,22 @@ def outputFolderName(outfolder, datagroups, doStatOnly, postfix): "Fitting multiple channels with 'wwidth' or decorMassWidth is not currently supported since this can lead to inconsistent treatment of mass variations between channels." ) - writer = tensorwriter.TensorWriter( + writer_kwargs = dict( sparse=args.sparse, allow_negative_expectation=args.allowNegativeExpectation, systematic_type=args.systematicType, add_bin_by_bin_stat_to_data_cov=args.addMCStatToCovariance, ) + # Forward the empty-bin-systematic knobs only when actually requested, so + # this script stays compatible with rabbit versions predating them (both + # are off by default; using them requires a rabbit with these TensorWriter + # arguments). + if args.clipSystVariations: + writer_kwargs["clip_syst_variations"] = args.clipSystVariations + if args.zeroSystLowNeff: + writer_kwargs["zero_syst_low_neff"] = args.zeroSystLowNeff + writer_kwargs["zero_syst_low_neff_procs"] = args.zeroSystLowNeffProcs + writer = tensorwriter.TensorWriter(**writer_kwargs) if args.fitresult is not None: # set data from external fitresult file From 694b381c4588225494db76f69eafe17d935148c1 Mon Sep 17 00:00:00 2001 From: Luca Lavezzo Date: Tue, 21 Jul 2026 17:20:45 -0400 Subject: [PATCH 2/2] Bump rabbit submodule to include #146 (empty-bin systematic knobs) WMass/rabbit#146 is merged (5a01cb4), adding the TensorWriter clip_syst_variations / zero_syst_low_neff arguments that the new setupRabbit flags forward to. Bumps the pin 948a94a -> 5a01cb4 (only #146 in between) so --clipSystVariations / --zeroSystLowNeff are usable. Co-Authored-By: Claude Opus 4.8 --- rabbit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rabbit b/rabbit index 948a94acf..5a01cb4b6 160000 --- a/rabbit +++ b/rabbit @@ -1 +1 @@ -Subproject commit 948a94acfb4add5807f901013fd5fc886b4eaee4 +Subproject commit 5a01cb4b63a679154900ec4c69a3da7ddad44151