Skip to content

Speed up pulseq_rs import by integrating gradient moments in NumPy. - #194

Merged
J-Endres merged 2 commits into
release-v1.1.3from
dev_mz_pulseq_import
Oct 19, 2026
Merged

J-Endres merged 2 commits into
release-v1.1.3from
dev_mz_pulseq_import

Conversation

@mzaiss

@mzaiss mzaiss commented Sep 26, 2026

Copy link
Copy Markdown
Collaborator

Resolves issue #175 The parser was already fast. The conversion called PyGradient.integrate once per event. Moments now come from one cumulative piecewise-linear integral per gradient, which covers trapezoids, extended trapezoids, and arbitrary shapes. Results match the old importer.

exact_trajectories=True (default):

File Old New
pp_mprage.seq 26 s 3.6 s
pp_radial.seq 0.80 s 0.22 s
mrseq_spiral.seq 5.6 s 0.43 s
pp_tse.seq 0.41 s 0.10 s
mrseq_radial_1_5.seq 3.0 s 0.24 s
mrseq_spiral_1.5.seq 3.0 s 0.23 s

The parser was already fast. The conversion called PyGradient.integrate once per event. Moments now come from one cumulative piecewise-linear integral per gradient, which covers trapezoids, extended trapezoids, and arbitrary shapes. Results match the old importer.

exact_trajectories=True (default):

| File | Old | New |
|---|---:|---:|
| pp_mprage.seq | 26 s | 3.6 s |
| pp_radial.seq | 0.80 s | 0.22 s |
| mrseq_spiral.seq | 5.6 s | 0.43 s |
| pp_tse.seq | 0.41 s | 0.10 s |
| mrseq_radial_1_5.seq | 3.0 s | 0.24 s |
| mrseq_spiral_1.5.seq | 3.0 s | 0.23 s |
@github-actions

Copy link
Copy Markdown

Simulation test: main (before) vs. this PR (after)

Sequence Status max mag NRMSE max phase RMSE max runtime Δ
mr0_DREAM_STE_seq ✅ 0.00e+00 0.00e+00 +3.9%
mr0_DWI_SE_EPI ✅ 0.00e+00 0.00e+00 -0.6%
mr0_EPI_2D_seq ✅ 0.00e+00 0.00e+00 +7.7%
mr0_FID_seq ✅ 0.00e+00 0.00e+00 +2.1%
mr0_FLASH_2D_seq ✅ 0.00e+00 0.00e+00 +5.2%
mr0_GRE_to_FLASH ⚠️ – – –
mr0_RARE_2D_seq ✅ 0.00e+00 0.00e+00 +1.6%
mr0_SE_CPMG_seq ✅ 0.00e+00 0.00e+00 +4.5%
mr0_STE_3pulses_5echoes_seq ✅ 0.00e+00 0.00e+00 +4.0%
mr0_TSE_2D_multi_shot_seq ✅ 0.00e+00 0.00e+00 +1.0%
mr0_bSSFP_2D_seq ✅ 0.00e+00 0.00e+00 +6.1%
mr0_diffusion_prep_STEAM_2D_seq ✅ 0.00e+00 0.00e+00 +5.6%
✅ mr0_DREAM_STE_seq: All tests passed.

mr0_DREAM_STE_seq

✅ mr0_DWI_SE_EPI: All tests passed.

mr0_DWI_SE_EPI

✅ mr0_EPI_2D_seq: All tests passed.

mr0_EPI_2D_seq

✅ mr0_FID_seq: All tests passed.

mr0_FID_seq

✅ mr0_FLASH_2D_seq: All tests passed.

mr0_FLASH_2D_seq

⚠️ mr0_GRE_to_FLASH: No comparison possible: [Errno 2] No such file or directory: '/home/runner/work/MRzero-Core/MRzero-Core/tests/simulation_test/ref_files/mr0_GRE_to_FLASH.seq.npz'
✅ mr0_RARE_2D_seq: All tests passed.

mr0_RARE_2D_seq

✅ mr0_SE_CPMG_seq: All tests passed.

mr0_SE_CPMG_seq

✅ mr0_STE_3pulses_5echoes_seq: All tests passed.

mr0_STE_3pulses_5echoes_seq

✅ mr0_TSE_2D_multi_shot_seq: All tests passed.

mr0_TSE_2D_multi_shot_seq

✅ mr0_bSSFP_2D_seq: All tests passed.

mr0_bSSFP_2D_seq

✅ mr0_diffusion_prep_STEAM_2D_seq: All tests passed.

mr0_diffusion_prep_STEAM_2D_seq

Workflow run — raw .npz data is attached as artifacts.

@J-Endres J-Endres left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The python side of the importer already was AI-generated; if the results are identical I trust this to work as expected.

@J-Endres
J-Endres changed the base branch from main to release-v1.1.3 October 19, 2026 08:14
@J-Endres
J-Endres merged commit 33f1124 into release-v1.1.3 Oct 19, 2026
33 checks passed
@J-Endres
J-Endres deleted the dev_mz_pulseq_import branch October 19, 2026 08:16
This was referenced Oct 19, 2026
J-Endres added a commit that referenced this pull request Oct 19, 2026
* fix: Match unit convention of pulse.freq_offset between pydissect and import_pulseq_rs to Hz (#197)

* Speed up pulseq_rs import by integrating gradient moments in NumPy. (#194)

The parser was already fast. The conversion called PyGradient.integrate once per event. Moments now come from one cumulative piecewise-linear integral per gradient, which covers trapezoids, extended trapezoids, and arbitrary shapes. Results match the old importer.

exact_trajectories=True (default):

| File | Old | New |
|---|---:|---:|
| pp_mprage.seq | 26 s | 3.6 s |
| pp_radial.seq | 0.80 s | 0.22 s |
| mrseq_spiral.seq | 5.6 s | 0.43 s |
| pp_tse.seq | 0.41 s | 0.10 s |
| mrseq_radial_1_5.seq | 3.0 s | 0.24 s |
| mrseq_spiral_1.5.seq | 3.0 s | 0.23 s |

* Cast values to native float before writing mrd header (#189)

* chore: update version number and changelog

* feat: update pulseq-rs for more fixes and better pulseq support

* feat: add FID graph creation function

* chore: link pulsq-zero in docs, remove submodule

* chore: add changelog to docs

* chore: rename version to 1.2.0

* fix: zero size for one of the phantom axes no longer crash prepass

---------

Co-authored-by: FDietz <felix.dietz@fau.de>
Co-authored-by: mzaiss <mzaiss@users.noreply.github.com>
Co-authored-by: David Schote <42237900+schote@users.noreply.github.com>
Co-authored-by: Jonathan Endres <jonathan.endres@uk-erlangen.de>
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