Skip to content

madspace: bind LHEEvent.alpha_qcd to the right member - #87

Merged
oliviermattelaer merged 1 commit into
mainfrom
claude/madspace-alpha-qcd-binding
Sep 2, 2026
Merged

oliviermattelaer merged 1 commit into
mainfrom
claude/madspace-alpha-qcd-binding

Conversation

@oliviermattelaer

Copy link
Copy Markdown
Contributor

The bug

madspace/src/python/madspace.cpp bound LHEEvent.alpha_qcd to &LHEEvent::process_id:

.def_readwrite("alpha_qed", &LHEEvent::alpha_qed)
.def_readwrite("alpha_qcd", &LHEEvent::process_id)   // <- wrong member

The correct member is &LHEEvent::alpha_qcd (double, declared in madspace/include/madspace/driver/lhe_output.hpp:61). Present since the line was first written (391f807c3, "started implementing LHE output") — never correct.

Observed from Python before the fix:

>>> e = ms.LHEEvent(process_id=7, alpha_qcd=0.118)
>>> e.alpha_qcd
7
>>> e.alpha_qcd = 0.118
TypeError: incompatible function arguments ... (arg0: typing.SupportsInt)

The generated stub was self-contradictory too: __init__(..., alpha_qcd: SupportsFloat) next to alpha_qcd -> int. It regenerates correctly now.

Blast radius

Nothing consumed it. alpha_qcd is only ever read/written through the C++ struct (event_generator.cpp, lhe_output.cpp, io.hpp), never through the Python attribute — no use in madspace/tests, MadGraph7's mg7 templates, MadSpin, or the acceptance tests. LHE files produced by the normal combine_to_lhe path were and are correct, since that never touches the binding. The reachable hazard was the Python-facing path only: an LHEEvent built or edited from Python and handed to LHEFileWriter.

The two members have different types (double vs int), so the mis-binding was partly self-announcing on the setter (TypeError on any float) but silent on the getter — reads just returned the process id.

Audit of the surrounding bindings

Checked all 167 def_readwrite/def_readonly bindings in madspace.cpp mechanically (Python name vs. bound member name, and bound class vs. enclosing py::classh). This was the only mismatch. Also hand-checked the py::init argument names and orders of the whole LHE block — LHEHeader, LHEProcess, LHEMeta, LHEParticle, LHEEvent, SubprocArgs — against their struct declarations; all correct.

Tests

Two additions to madspace/tests/test_lhe.py, both failing before the fix and passing after:

  • test_event_attributes_are_bound_to_their_own_members — every LHEEvent attribute reads back its own value, via the constructor and via the setters (catches any future aliasing in that block, not just this field).
  • test_event_header_line_written_to_lhe — sets the fields one by one and checks the NUP IDPRUP XWGTUP SCALUP AQEDUP AQCDUP header line of the file written by LHEFileWriter.

They need the built extension, which is exactly what CI already does: .github/workflows/madspace.yml runs pytest {project}/madspace/tests against the cibuildwheel-built wheel. No CI changes needed.

Suite

pytest madspace/tests (local, macOS arm64, Python 3.14):

  • before: 4 failed, 1470 passed, 2 skipped
  • after: 4 failed, 1472 passed, 2 skipped

The 4 failures are pre-existing and need scipy (test_double_t.py); test_flow.py/test_mlp.py need torch. Neither is installed locally, both are installed in CI.

🤖 Generated with Claude Code

The pybind11 binding for LHEEvent exposed `alpha_qcd` as
`&LHEEvent::process_id`, so reading `event.alpha_qcd` from Python
returned the (int) process id, and assigning a float to it raised
TypeError. Point it at `&LHEEvent::alpha_qcd`.

Add two regression tests: one asserting every LHEEvent attribute reads
back its own value through both the constructor and the setters, and one
checking the AQCDUP column of the event header line written by
LHEFileWriter.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@oliviermattelaer

Copy link
Copy Markdown
Contributor Author

I guess that this should be merge quickly.

@theoheimel

Copy link
Copy Markdown
Contributor

looks good

@oliviermattelaer
oliviermattelaer merged commit 83dfa6e into main Sep 2, 2026
580 of 581 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.

2 participants