Skip to content

mg7 1 -> N processes: decaying mass without parameter_dict, decay-aware observables, no histograms in MadSpin, 1->3 CI test - #228

Merged
oliviermattelaer merged 2 commits into
mainfrom
fix-decaying-mass-loopmodel
Oct 8, 2026
Merged

oliviermattelaer merged 2 commits into
mainfrom
fix-decaying-mass-loopmodel

Conversation

@oliviermattelaer

Copy link
Copy Markdown
Contributor

Problem

With madspace built, MadSpin (spinmode none) generates its decays through output mg7, and test_hepmc_decay / test_lhe_none_decay failed (no *_decayed.lhe.gz). Without madspace they take the madevent fallback, which is why nobody noticed. Two bugs, both in the default [histograms] of a 1 -> N process (81e9a13):

  1. RunCardMG7._decaying_mass read model.get('parameter_dict'), and only a ModelReader has that property. A LoopModel raised PhysicsObjectError, which the except didn't catch, so output crashed. A plain Model raised KeyError and silently gave mass 0.
  2. madspace Observable assumes two beams (ignore_incoming drops the first 2 momenta, and the sqrt_s kernel is p[0]+p[1]). For a decay, the first decay product dropped out of every selection. z > mu+ mu- asked for lepton_2 and the launcher died with "absolute value of order index must be smaller or equal to number of selected PIDs". In t > b e+ ve, every b histogram sat at 0. This happens with plain output mg7 of any decay, not only under MadSpin.

Fix

  • _parameter_value: if the model has a parameter_dict, use it. Otherwise evaluate from the default external parameter values in a scratch namespace (internal masses such as mdl_MW in sm-full included). The model's own parameters are not touched.
  • build_observable in the mg7 launcher: with one incoming particle, the selection runs over all momenta (ignore_incoming=False) and the incoming pid is set to 0, which belongs to no group. Used for cuts, integration histograms and event histograms.
  • No default sqrt_s histogram for a decay: madspace's kernel adds two beams, and for a decay the value would be a constant anyway.
  • MadSpin's mg7 decay runs now drop [histograms] altogether (like set histograms OFF). Nobody looks at the plots of a decay pool, and each one costs an observable evaluation per event.

Tests

  • New test_decay_1to3_mg7 (added to acceptancetest_mg7_bundle_1): runs t > b e+ ve through mg7 and pins the width to madevent (0.1636 ± 0.0002 GeV). It also checks the default histograms: no sqrt_s, every momentum histogram holds the full width in range, and the e+ ve pair mass peaks in the bin containing MW. On origin/main it fails: bottom-pt has everything in its first bin and sqrt_s is all overflow.
  • New unit test test_decaying_mass_without_parameter_dict (plain Model and LoopModel built from sm-full, where MW is internal). test_decay_process_uses_the_decaying_mass is updated for the dropped sqrt_s.
  • Locally, with madspace built:
    • test_hepmc_decay, test_lhe_none_decay, test_decay_1to3_mg7, test_w_production_with_ms_decay_mg7, test_madspin_mixed_flavor_decay_log_summary_mg7: Ran 5, OK. On origin/main the first two fail with the PhysicsObjectError above.
    • All test_banner.py + test_mg7_launch.py classes: Ran 157, OK.
  • Physics check on MadSpin's z > mu+ mu- decay histograms, before histograms were switched off there: the pair mass falls in the [90, 92] GeV bin, and the muon pT edge is at m_Z/2.

🤖 Generated with Claude Code

…decay-aware observables

Two bugs behind the [histograms] defaults of a 1 -> N process (81e9a13),
both hit by MadSpin's mg7 decay generator (spinmode none, madspace built):

- RunCardMG7._decaying_mass read model.get('parameter_dict'), which only a
  ModelReader has. A LoopModel raised PhysicsObjectError (not caught, so
  `output` crashed) and a plain Model silently gave 0. The mass is now
  evaluated from the default values of the external parameters, in a
  scratch namespace (internal masses such as MW in sm-full included),
  leaving the model untouched.

- madspace's Observable takes the first two momenta to be the beams, so
  for a decay the first decay product was dropped from every selection:
  `z > mu+ mu-` asked for lepton_2 and the launcher died with "absolute
  value of order index must be smaller or equal to number of selected
  PIDs" (no events.npy). build_observable() now runs the selection over
  all momenta with the incoming pid zeroed when there is one incoming
  particle (cuts, integration and event histograms). sqrt_s, whose
  kernel adds two beams, is no longer a default histogram of a decay.

Fixes test_hepmc_decay and test_lhe_none_decay with madspace built.
…n CI

- generate_events_mg7 drops [histograms] from the decay run card (as
  `set histograms OFF`): nobody looks at the plots of a decay pool and they
  cost an observable evaluation per event.
- test_decay_1to3_mg7: t > b e+ ve through output mg7, the width pinned to
  madevent (0.1636 GeV), and the default histograms checked (no sqrt_s,
  every momentum histogram holding the full width in range, e+ ve pair mass
  peaking at MW). On origin/main it fails: bottom-pt has everything at 0 (the
  b dropped from the selection) and sqrt_s is in overflow. Added to
  acceptancetest_mg7_bundle_1.
@oliviermattelaer
oliviermattelaer merged commit 633e255 into main Oct 8, 2026
175 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.

1 participant