Conversation
…e conversion from CircuitExtractor and use snapshots on batching behaviour in the softrz runtime
There was a problem hiding this comment.
Pull request overview
This PR introduces an analytics/trace facility by defining a Pydantic-based selene_core.Trace event model, emitting traces from the simulator instruction log, and packaging a JSON schema into the selene-core distribution for later validation/loading.
Changes:
- Add
selene_core.tracePydantic models for event traces, including JSON (de)serialization. - Extend
CircuitExtractor/ShotInstructionsto produce aTraceviaget_trace()and snapshot it in existing batching tests. - Add a Hatch build hook to generate and ship the
TraceJSON schema in the_distbundle; addpydanticdependency.
Reviewed changes
Copilot reviewed 9 out of 10 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
uv.lock |
Locks in pydantic as a dependency. |
selene-sim/python/selene_sim/event_hooks/instruction_log.py |
Builds a Trace from instruction logs (get_trace). |
selene-ext/runtimes/soft_rz/python/tests/test_batching.py |
Adds trace snapshot assertions and updates backend imports. |
selene-ext/runtimes/soft_rz/python/tests/snapshots/.../trace_batching_*.json |
New trace snapshots for batching scenarios. |
selene-core/python/selene_core/trace.py |
New Pydantic trace/event schema and helpers. |
selene-core/pyproject.toml |
Adds pydantic dependency; wires schema generation into build cache keys and build-system requirements. |
selene-core/hatch_build.py |
Generates and writes Trace JSON schema into _dist during build. |
justfile |
Minor whitespace change. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| case Rzz(qubit0=qubit0, qubit1=qubit1, theta=theta): | ||
| event = GateEvent( | ||
| gate_name="Rzz", | ||
| qubits=[qubit0, qubit1], | ||
| args={"theta": theta}, | ||
| ) |
There was a problem hiding this comment.
GateEvent doesn't define an args field (and extra='ignore'), so the theta value passed here will be dropped from the emitted trace. Use params or add an explicit args field to the trace schema/model.
| case Rxy(qubit=qubit, theta=theta, phi=phi): | ||
| event = GateEvent( | ||
| gate_name="Rxy", | ||
| qubits=[qubit], | ||
| args={ | ||
| "theta": theta, | ||
| "phi": phi, | ||
| }, | ||
| ) |
There was a problem hiding this comment.
GateEvent doesn't define an args field (and AbstractEvent is configured with extra='ignore'), so the theta/phi values provided here will be silently dropped from the serialized trace. Either add a typed args field to GateEvent (and schema), or encode these values using the existing params field (as done for user-program events).
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 10 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| match instruction.operation: | ||
| case CustomOperation(tag=tag, data=data): | ||
| trace.add_user_program_event( | ||
| CustomEvent(payload=OpaquePayload(tag=tag, data=data)), | ||
| index=user_program_event_index, | ||
| ) | ||
| user_program_event_index += 1 | ||
| case LocalBarrier(qubits=qubits, sleep_time=sleep_time): | ||
| trace.add_user_program_event( | ||
| GateEvent( |
There was a problem hiding this comment.
get_trace() has a lot of repeated add_user_program_event(...); user_program_event_index += 1 / add_runtime_event(...) boilerplate across the match cases, which makes the method harder to maintain when new operations are added. Consider introducing a small local helper (e.g., add_user(event) / add_runtime(event)) or factoring the Operation->Event conversion into a separate function/table to centralize the index increment and reduce duplication.
🤖 I have created a release *beep* *boop* --- ## [0.2.8](selene-core-v0.2.7...selene-core-v0.2.8) (2026-04-21) ### Features * add timing to builtin runtimes and batching options to softrz runtime ([#158](#158)) ([049e123](049e123)) * Traces for analytics ([#160](#160)) ([24b9978](24b9978)) ### Bug Fixes * classify lowered qir-qis bitcode as helios ([#157](#157)) ([67fca60](67fca60)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please).
🤖 I have created a release *beep* *boop* --- ## [0.2.14](selene-sim-v0.2.13...selene-sim-v0.2.14) (2026-04-21) ### Features * add timing to builtin runtimes and batching options to softrz runtime ([#158](#158)) ([049e123](049e123)) * Record simulated delays in event hooks ([#154](#154)) ([608884a](608884a)) * Traces for analytics ([#160](#160)) ([24b9978](24b9978)) ### Bug Fixes * classify lowered qir-qis bitcode as helios ([#157](#157)) ([67fca60](67fca60)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please).
Provides a pydantic trace format for recording events going into, and coming out of, a runtime during a run.
This can be extracted from a CircuitExtractor with
get_trace(), and then encoded as json. A schema is provided in selene-core's _dist bundle that may be used to validate the json.The trace can be loaded at a later point via pydantic. This provides a way of analysing the characteristics of a simulated run.