pulserver 0.4.0__tar.gz → 0.4.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (490) hide show
  1. {pulserver-0.4.0 → pulserver-0.4.2}/CMakeLists.txt +1 -1
  2. {pulserver-0.4.0 → pulserver-0.4.2}/PKG-INFO +4 -5
  3. {pulserver-0.4.0 → pulserver-0.4.2}/docs/api/design.md +7 -8
  4. {pulserver-0.4.0 → pulserver-0.4.2}/docs/api/ir.md +3 -2
  5. {pulserver-0.4.0 → pulserver-0.4.2}/docs/developer-guide/internals/index.md +1 -1
  6. {pulserver-0.4.0 → pulserver-0.4.2}/docs/developer-guide/internals/ir-cache.md +63 -24
  7. {pulserver-0.4.0 → pulserver-0.4.2}/docs/developer-guide/internals/protocol-wire.md +14 -0
  8. {pulserver-0.4.0 → pulserver-0.4.2}/docs/developer-guide/internals/reconstruction-proxy.md +11 -4
  9. {pulserver-0.4.0 → pulserver-0.4.2}/docs/developer-guide/internals/virtual-scanner.md +5 -4
  10. {pulserver-0.4.0 → pulserver-0.4.2}/docs/developer-guide/terminology.md +2 -2
  11. {pulserver-0.4.0 → pulserver-0.4.2}/docs/explanations/architecture.md +2 -1
  12. {pulserver-0.4.0 → pulserver-0.4.2}/docs/explanations/reconstruction-session.md +12 -7
  13. {pulserver-0.4.0 → pulserver-0.4.2}/docs/explanations/safety-checks.md +3 -2
  14. {pulserver-0.4.0 → pulserver-0.4.2}/docs/explanations/scanner-representation.md +1 -1
  15. {pulserver-0.4.0 → pulserver-0.4.2}/docs/user-guide/reconstruction-client.md +17 -8
  16. {pulserver-0.4.0 → pulserver-0.4.2}/docs/user-guide/reconstruction-plugins.md +18 -6
  17. {pulserver-0.4.0 → pulserver-0.4.2}/docs/user-guide/running.md +30 -17
  18. {pulserver-0.4.0 → pulserver-0.4.2}/docs/user-guide/scanner-sequences.md +81 -32
  19. {pulserver-0.4.0 → pulserver-0.4.2}/gallery/01-course/01_protocol_to_image.py +3 -3
  20. {pulserver-0.4.0 → pulserver-0.4.2}/pyproject.toml +3 -4
  21. {pulserver-0.4.0 → pulserver-0.4.2}/src/c/cache/pulseg_cache.c +63 -12
  22. {pulserver-0.4.0 → pulserver-0.4.2}/src/c/core/pulseg_core.c +125 -1
  23. {pulserver-0.4.0 → pulserver-0.4.2}/src/c/core/pulseg_error.c +6 -0
  24. {pulserver-0.4.0 → pulserver-0.4.2}/src/c/include/pulseg/pulseg_collection.h +77 -43
  25. {pulserver-0.4.0 → pulserver-0.4.2}/src/c/include/pulseg/pulseg_errors.h +1 -1
  26. {pulserver-0.4.0 → pulserver-0.4.2}/src/c/include/pulseg/pulseg_playout.h +69 -5
  27. {pulserver-0.4.0 → pulserver-0.4.2}/src/c/include/pulseg/pulseg_types.h +78 -40
  28. {pulserver-0.4.0 → pulserver-0.4.2}/src/c/include/pulseq/pulseq_types.h +8 -3
  29. {pulserver-0.4.0 → pulserver-0.4.2}/src/c/playout/pulseg_playout.c +278 -3
  30. {pulserver-0.4.0 → pulserver-0.4.2}/src/c/pulseg_internal.h +36 -14
  31. {pulserver-0.4.0 → pulserver-0.4.2}/src/c/structure/pulseg_descriptor.c +48 -18
  32. {pulserver-0.4.0 → pulserver-0.4.2}/src/c/structure/pulseg_getters.c +282 -172
  33. {pulserver-0.4.0 → pulserver-0.4.2}/src/c/structure/pulseg_repetition.c +11 -9
  34. {pulserver-0.4.0 → pulserver-0.4.2}/src/cpp/ir/collection.cpp +12 -0
  35. {pulserver-0.4.0 → pulserver-0.4.2}/src/cpp/ir/dedup.cpp +1 -0
  36. pulserver-0.4.2/src/cpp/ir/gradient_stretch.cpp +332 -0
  37. {pulserver-0.4.0 → pulserver-0.4.2}/src/cpp/ir/pulseg_convert.h +5 -5
  38. {pulserver-0.4.0 → pulserver-0.4.2}/src/cpp/ir/structure.cpp +101 -0
  39. {pulserver-0.4.0 → pulserver-0.4.2}/src/cpp/module.cpp +106 -36
  40. {pulserver-0.4.0 → pulserver-0.4.2}/src/cpp/playout.cpp +2 -0
  41. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_plugins.py +0 -4
  42. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/_user.py +36 -3
  43. pulserver-0.4.2/src/pulserver/_zoo/recon/nufft.py +3 -0
  44. pulserver-0.4.2/src/pulserver/_zoo/recon/pics.py +3 -0
  45. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/sequences/bssfp2d.py +2 -2
  46. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/sequences/fse3d.py +14 -5
  47. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/sequences/gre3d.py +3 -3
  48. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/sequences/gre_multiecho2d.py +2 -2
  49. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/sequences/gre_multiecho3d.py +4 -4
  50. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/sequences/gre_spiral2d.py +2 -2
  51. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/sequences/gre_stack_of_spirals3d.py +2 -2
  52. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/sequences/mprage3d.py +11 -5
  53. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/sequences/mprage_stack_of_spirals3d.py +9 -3
  54. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/sequences/mprage_stack_of_stars3d.py +2 -2
  55. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/sequences/se3d.py +2 -2
  56. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/sequences/se_spiral2d.py +2 -2
  57. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/sequences/se_stack_of_spirals3d.py +2 -2
  58. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/sequences/zte3d.py +2 -2
  59. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/design/__init__.py +3 -2
  60. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/design/_entries.py +95 -13
  61. pulserver-0.4.2/src/pulserver/design/_options.py +160 -0
  62. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/design/_plugin.py +155 -61
  63. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/host/_command.py +9 -18
  64. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/host/_limits.py +25 -15
  65. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/host/_server.py +7 -9
  66. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/host/_service.py +46 -60
  67. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/host/_store.py +8 -1
  68. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/ir/__init__.py +4 -3
  69. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/ir/_convert.py +6 -0
  70. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/ir/_playout.py +47 -8
  71. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/ir/_source.py +54 -7
  72. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/ir/_waves.py +35 -16
  73. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/protocol/_wire.py +17 -8
  74. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/proxy/_designs.py +1 -24
  75. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/proxy/_enrich.py +14 -0
  76. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/proxy/_motion.py +67 -7
  77. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/proxy/_proxy.py +130 -38
  78. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/proxy/_seqdesc.py +10 -2
  79. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/recon/_correct.py +38 -13
  80. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/recon/_runtime/mrd2dicom.py +7 -1
  81. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/recon/_runtime/offline.py +13 -4
  82. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/recon/handlers/nufft.py +9 -42
  83. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/recon/handlers/pics.py +53 -16
  84. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/virtual/_console.py +1 -1
  85. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/virtual/_fourier.py +3 -3
  86. pulserver-0.4.2/tests/_host.py +138 -0
  87. {pulserver-0.4.0 → pulserver-0.4.2}/tests/fixtures/sequences/epi_2d_main.seq +2 -2
  88. {pulserver-0.4.0 → pulserver-0.4.2}/tests/fixtures/sequences/mprage_stack_of_spirals_3d.seq +2 -2
  89. {pulserver-0.4.0 → pulserver-0.4.2}/tests/fixtures/sequences/zte_3d.seq +2 -2
  90. {pulserver-0.4.0 → pulserver-0.4.2}/tests/native/read_cache_summary.c +37 -18
  91. {pulserver-0.4.0 → pulserver-0.4.2}/tests/recon/test_correct.py +34 -20
  92. {pulserver-0.4.0 → pulserver-0.4.2}/tests/recon/test_mrd2dicom.py +26 -0
  93. {pulserver-0.4.0 → pulserver-0.4.2}/tests/recon/test_nufft.py +2 -2
  94. {pulserver-0.4.0 → pulserver-0.4.2}/tests/recon/test_pics.py +75 -0
  95. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_console_sequences.py +1 -36
  96. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_design_service.py +43 -0
  97. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_ir.py +17 -12
  98. pulserver-0.4.2/tests/test_ir_gradient_stretch.py +292 -0
  99. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_ir_grouping.py +4 -4
  100. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_ir_playout.py +29 -0
  101. pulserver-0.4.2/tests/test_ir_prescan.py +96 -0
  102. pulserver-0.4.2/tests/test_ir_prescan_tour.py +125 -0
  103. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_ir_rf.py +90 -0
  104. pulserver-0.4.2/tests/test_ir_rf_freq.py +103 -0
  105. pulserver-0.4.2/tests/test_ir_timing.py +139 -0
  106. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_limits.py +46 -6
  107. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_motion.py +57 -6
  108. pulserver-0.4.2/tests/test_plugin_options.py +279 -0
  109. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_proxy.py +120 -4
  110. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_virtual_fourier.py +46 -0
  111. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_wire.py +5 -0
  112. pulserver-0.4.2/tests/test_zoo_defaults.py +116 -0
  113. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_zoo_evaluation.py +6 -2
  114. pulserver-0.4.2/tests/test_zoo_fov_offset.py +205 -0
  115. pulserver-0.4.2/tests/test_zoo_mrd_labels.py +138 -0
  116. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_zoo_wave.py +3 -5
  117. pulserver-0.4.0/src/cpp/ir/repetition.cpp +0 -216
  118. pulserver-0.4.0/src/pulserver/_zoo/parameters/bssfp2d/retrospective.toml +0 -2
  119. pulserver-0.4.0/src/pulserver/_zoo/parameters/fse3d/dual_region.toml +0 -2
  120. pulserver-0.4.0/src/pulserver/_zoo/parameters/fse3d/navigator.toml +0 -2
  121. pulserver-0.4.0/src/pulserver/_zoo/parameters/fse3d/optimized.toml +0 -2
  122. pulserver-0.4.0/src/pulserver/_zoo/parameters/fse3d/shuffling.toml +0 -2
  123. pulserver-0.4.0/src/pulserver/_zoo/parameters/fse3d/wave.toml +0 -2
  124. pulserver-0.4.0/src/pulserver/_zoo/parameters/gre3d/full_plane.toml +0 -2
  125. pulserver-0.4.0/src/pulserver/_zoo/parameters/gre3d/wave.toml +0 -2
  126. pulserver-0.4.0/src/pulserver/_zoo/parameters/gre_multiecho2d/bipolar.toml +0 -2
  127. pulserver-0.4.0/src/pulserver/_zoo/parameters/gre_multiecho3d/bipolar.toml +0 -2
  128. pulserver-0.4.0/src/pulserver/_zoo/parameters/gre_multiecho3d/full_plane.toml +0 -2
  129. pulserver-0.4.0/src/pulserver/_zoo/parameters/gre_multiecho3d/wave.toml +0 -2
  130. pulserver-0.4.0/src/pulserver/_zoo/parameters/gre_spiral2d/variable_density.toml +0 -2
  131. pulserver-0.4.0/src/pulserver/_zoo/parameters/gre_stack_of_spirals3d/variable_density.toml +0 -2
  132. pulserver-0.4.0/src/pulserver/_zoo/parameters/mprage3d/navigator.toml +0 -2
  133. pulserver-0.4.0/src/pulserver/_zoo/parameters/mprage3d/shuffling.toml +0 -2
  134. pulserver-0.4.0/src/pulserver/_zoo/parameters/mprage3d/wave.toml +0 -2
  135. pulserver-0.4.0/src/pulserver/_zoo/parameters/mprage_stack_of_spirals3d/variable_density.toml +0 -2
  136. pulserver-0.4.0/src/pulserver/_zoo/parameters/se3d/full_plane.toml +0 -2
  137. pulserver-0.4.0/src/pulserver/_zoo/parameters/se_spiral2d/variable_density.toml +0 -2
  138. pulserver-0.4.0/src/pulserver/_zoo/parameters/se_stack_of_spirals3d/variable_density.toml +0 -2
  139. pulserver-0.4.0/src/pulserver/_zoo/parameters/zte3d/meridian.toml +0 -2
  140. pulserver-0.4.0/src/pulserver/_zoo/recon/nufft.py +0 -3
  141. pulserver-0.4.0/src/pulserver/_zoo/recon/pics.py +0 -3
  142. pulserver-0.4.0/src/pulserver/design/_options.py +0 -133
  143. pulserver-0.4.0/tests/_host.py +0 -72
  144. pulserver-0.4.0/tests/test_ir_groups.py +0 -85
  145. pulserver-0.4.0/tests/test_ir_repetition_gradients.py +0 -150
  146. pulserver-0.4.0/tests/test_plugin_options.py +0 -240
  147. {pulserver-0.4.0 → pulserver-0.4.2}/.claude/skills/build-and-test/SKILL.md +0 -0
  148. {pulserver-0.4.0 → pulserver-0.4.2}/.claude/skills/write-documentation/SKILL.md +0 -0
  149. {pulserver-0.4.0 → pulserver-0.4.2}/.dockerignore +0 -0
  150. {pulserver-0.4.0 → pulserver-0.4.2}/.gitattributes +0 -0
  151. {pulserver-0.4.0 → pulserver-0.4.2}/.github/DISCUSSION_TEMPLATE/ideas.yml +0 -0
  152. {pulserver-0.4.0 → pulserver-0.4.2}/.github/DISCUSSION_TEMPLATE/q-a.yml +0 -0
  153. {pulserver-0.4.0 → pulserver-0.4.2}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  154. {pulserver-0.4.0 → pulserver-0.4.2}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  155. {pulserver-0.4.0 → pulserver-0.4.2}/.github/ISSUE_TEMPLATE/documentation.yml +0 -0
  156. {pulserver-0.4.0 → pulserver-0.4.2}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  157. {pulserver-0.4.0 → pulserver-0.4.2}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  158. {pulserver-0.4.0 → pulserver-0.4.2}/.github/dependabot.yml +0 -0
  159. {pulserver-0.4.0 → pulserver-0.4.2}/.github/workflows/codeql.yml +0 -0
  160. {pulserver-0.4.0 → pulserver-0.4.2}/.github/workflows/console.yml +0 -0
  161. {pulserver-0.4.0 → pulserver-0.4.2}/.github/workflows/docs.yml +0 -0
  162. {pulserver-0.4.0 → pulserver-0.4.2}/.github/workflows/fields.yml +0 -0
  163. {pulserver-0.4.0 → pulserver-0.4.2}/.github/workflows/image.yml +0 -0
  164. {pulserver-0.4.0 → pulserver-0.4.2}/.github/workflows/koma.yml +0 -0
  165. {pulserver-0.4.0 → pulserver-0.4.2}/.github/workflows/style.yml +0 -0
  166. {pulserver-0.4.0 → pulserver-0.4.2}/.github/workflows/tags-release.yml +0 -0
  167. {pulserver-0.4.0 → pulserver-0.4.2}/.github/workflows/test-ci.yml +0 -0
  168. {pulserver-0.4.0 → pulserver-0.4.2}/.github/workflows/wheels.yml +0 -0
  169. {pulserver-0.4.0 → pulserver-0.4.2}/.gitignore +0 -0
  170. {pulserver-0.4.0 → pulserver-0.4.2}/.pre-commit-config.yaml +0 -0
  171. {pulserver-0.4.0 → pulserver-0.4.2}/AGENTS.md +0 -0
  172. {pulserver-0.4.0 → pulserver-0.4.2}/CODE_OF_CONDUCT.md +0 -0
  173. {pulserver-0.4.0 → pulserver-0.4.2}/CONTRIBUTING.md +0 -0
  174. {pulserver-0.4.0 → pulserver-0.4.2}/LICENSE +0 -0
  175. {pulserver-0.4.0 → pulserver-0.4.2}/LICENSES/gadgetron-python-MIT.txt +0 -0
  176. {pulserver-0.4.0 → pulserver-0.4.2}/LICENSES/python-ismrmrd-server-MIT.txt +0 -0
  177. {pulserver-0.4.0 → pulserver-0.4.2}/NEXT.md +0 -0
  178. {pulserver-0.4.0 → pulserver-0.4.2}/README.md +0 -0
  179. {pulserver-0.4.0 → pulserver-0.4.2}/SECURITY.md +0 -0
  180. {pulserver-0.4.0 → pulserver-0.4.2}/SKILLS.md +0 -0
  181. {pulserver-0.4.0 → pulserver-0.4.2}/codecov.yml +0 -0
  182. {pulserver-0.4.0 → pulserver-0.4.2}/docker/Dockerfile +0 -0
  183. {pulserver-0.4.0 → pulserver-0.4.2}/docker/compose.yaml +0 -0
  184. {pulserver-0.4.0 → pulserver-0.4.2}/docker/entrypoint.sh +0 -0
  185. {pulserver-0.4.0 → pulserver-0.4.2}/docker/limits/limits.txt +0 -0
  186. {pulserver-0.4.0 → pulserver-0.4.2}/docker/smoke.py +0 -0
  187. {pulserver-0.4.0 → pulserver-0.4.2}/docs/_static/architecture-dark.svg +0 -0
  188. {pulserver-0.4.0 → pulserver-0.4.2}/docs/_static/architecture.svg +0 -0
  189. {pulserver-0.4.0 → pulserver-0.4.2}/docs/_static/capabilities.js +0 -0
  190. {pulserver-0.4.0 → pulserver-0.4.2}/docs/_static/context-dark.svg +0 -0
  191. {pulserver-0.4.0 → pulserver-0.4.2}/docs/_static/context.svg +0 -0
  192. {pulserver-0.4.0 → pulserver-0.4.2}/docs/_static/pulseg-dark.svg +0 -0
  193. {pulserver-0.4.0 → pulserver-0.4.2}/docs/_static/pulseg.svg +0 -0
  194. {pulserver-0.4.0 → pulserver-0.4.2}/docs/_static/pulserver-logo-dark.svg +0 -0
  195. {pulserver-0.4.0 → pulserver-0.4.2}/docs/_static/pulserver-logo.svg +0 -0
  196. {pulserver-0.4.0 → pulserver-0.4.2}/docs/_static/pulserver-mark-dark.svg +0 -0
  197. {pulserver-0.4.0 → pulserver-0.4.2}/docs/_static/pulserver-mark.svg +0 -0
  198. {pulserver-0.4.0 → pulserver-0.4.2}/docs/_static/pulserver.css +0 -0
  199. {pulserver-0.4.0 → pulserver-0.4.2}/docs/_static/repetition-dark.svg +0 -0
  200. {pulserver-0.4.0 → pulserver-0.4.2}/docs/_static/repetition.svg +0 -0
  201. {pulserver-0.4.0 → pulserver-0.4.2}/docs/_static/safety-dark.svg +0 -0
  202. {pulserver-0.4.0 → pulserver-0.4.2}/docs/_static/safety.svg +0 -0
  203. {pulserver-0.4.0 → pulserver-0.4.2}/docs/_static/session-dark.svg +0 -0
  204. {pulserver-0.4.0 → pulserver-0.4.2}/docs/_static/session.svg +0 -0
  205. {pulserver-0.4.0 → pulserver-0.4.2}/docs/_static/virtual-dark.svg +0 -0
  206. {pulserver-0.4.0 → pulserver-0.4.2}/docs/_static/virtual.svg +0 -0
  207. {pulserver-0.4.0 → pulserver-0.4.2}/docs/_templates/autosummary/base.rst +0 -0
  208. {pulserver-0.4.0 → pulserver-0.4.2}/docs/_templates/autosummary/class.rst +0 -0
  209. {pulserver-0.4.0 → pulserver-0.4.2}/docs/_templates/autosummary/enum.rst +0 -0
  210. {pulserver-0.4.0 → pulserver-0.4.2}/docs/_templates/autosummary/function.rst +0 -0
  211. {pulserver-0.4.0 → pulserver-0.4.2}/docs/api/host.md +0 -0
  212. {pulserver-0.4.0 → pulserver-0.4.2}/docs/api/index.md +0 -0
  213. {pulserver-0.4.0 → pulserver-0.4.2}/docs/api/mrd.md +0 -0
  214. {pulserver-0.4.0 → pulserver-0.4.2}/docs/api/protocol.md +0 -0
  215. {pulserver-0.4.0 → pulserver-0.4.2}/docs/api/proxy.md +0 -0
  216. {pulserver-0.4.0 → pulserver-0.4.2}/docs/api/recon.md +0 -0
  217. {pulserver-0.4.0 → pulserver-0.4.2}/docs/api/validate.md +0 -0
  218. {pulserver-0.4.0 → pulserver-0.4.2}/docs/api/virtual.md +0 -0
  219. {pulserver-0.4.0 → pulserver-0.4.2}/docs/api_objects.py +0 -0
  220. {pulserver-0.4.0 → pulserver-0.4.2}/docs/colab.py +0 -0
  221. {pulserver-0.4.0 → pulserver-0.4.2}/docs/conf.py +0 -0
  222. {pulserver-0.4.0 → pulserver-0.4.2}/docs/developer-guide/documentation.md +0 -0
  223. {pulserver-0.4.0 → pulserver-0.4.2}/docs/developer-guide/index.md +0 -0
  224. {pulserver-0.4.0 → pulserver-0.4.2}/docs/developer-guide/installation.md +0 -0
  225. {pulserver-0.4.0 → pulserver-0.4.2}/docs/developer-guide/internals/calibration.md +0 -0
  226. {pulserver-0.4.0 → pulserver-0.4.2}/docs/developer-guide/internals/sar-ratios.md +0 -0
  227. {pulserver-0.4.0 → pulserver-0.4.2}/docs/developer-guide/releases.md +0 -0
  228. {pulserver-0.4.0 → pulserver-0.4.2}/docs/developer-guide/style.md +0 -0
  229. {pulserver-0.4.0 → pulserver-0.4.2}/docs/developer-guide/workflow.md +0 -0
  230. {pulserver-0.4.0 → pulserver-0.4.2}/docs/examples/course.md +0 -0
  231. {pulserver-0.4.0 → pulserver-0.4.2}/docs/examples/index.md +0 -0
  232. {pulserver-0.4.0 → pulserver-0.4.2}/docs/examples/tours.md +0 -0
  233. {pulserver-0.4.0 → pulserver-0.4.2}/docs/explanations/index.md +0 -0
  234. {pulserver-0.4.0 → pulserver-0.4.2}/docs/explanations/protocol.md +0 -0
  235. {pulserver-0.4.0 → pulserver-0.4.2}/docs/explanations/raw-data.md +0 -0
  236. {pulserver-0.4.0 → pulserver-0.4.2}/docs/explanations/reconstruction.md +0 -0
  237. {pulserver-0.4.0 → pulserver-0.4.2}/docs/explanations/virtual-scanner.md +0 -0
  238. {pulserver-0.4.0 → pulserver-0.4.2}/docs/figure_style.py +0 -0
  239. {pulserver-0.4.0 → pulserver-0.4.2}/docs/index.md +0 -0
  240. {pulserver-0.4.0 → pulserver-0.4.2}/docs/misc/contributors.md +0 -0
  241. {pulserver-0.4.0 → pulserver-0.4.2}/docs/misc/index.md +0 -0
  242. {pulserver-0.4.0 → pulserver-0.4.2}/docs/misc/license.md +0 -0
  243. {pulserver-0.4.0 → pulserver-0.4.2}/docs/misc/related.md +0 -0
  244. {pulserver-0.4.0 → pulserver-0.4.2}/docs/user-guide/index.md +0 -0
  245. {pulserver-0.4.0 → pulserver-0.4.2}/docs/user-guide/virtual-scanner.md +0 -0
  246. {pulserver-0.4.0 → pulserver-0.4.2}/gallery/01-course/02_sequence_plugin.py +0 -0
  247. {pulserver-0.4.0 → pulserver-0.4.2}/gallery/01-course/03_scanner_representation.py +0 -0
  248. {pulserver-0.4.0 → pulserver-0.4.2}/gallery/01-course/04_reconstruction_plugin.py +0 -0
  249. {pulserver-0.4.0 → pulserver-0.4.2}/gallery/01-course/05_recon_plugin.py +0 -0
  250. {pulserver-0.4.0 → pulserver-0.4.2}/gallery/01-course/06_testing_on_the_virtual_scanner.py +0 -0
  251. {pulserver-0.4.0 → pulserver-0.4.2}/gallery/01-course/README.rst +0 -0
  252. {pulserver-0.4.0 → pulserver-0.4.2}/gallery/01-course/_gallery_header.md +0 -0
  253. {pulserver-0.4.0 → pulserver-0.4.2}/gallery/02-tours/01_protocol_resolution.py +0 -0
  254. {pulserver-0.4.0 → pulserver-0.4.2}/gallery/02-tours/02_segmentation.py +0 -0
  255. {pulserver-0.4.0 → pulserver-0.4.2}/gallery/02-tours/03_fov_offset_enrichment.py +0 -0
  256. {pulserver-0.4.0 → pulserver-0.4.2}/gallery/02-tours/README.rst +0 -0
  257. {pulserver-0.4.0 → pulserver-0.4.2}/gallery/02-tours/_gallery_header.md +0 -0
  258. {pulserver-0.4.0 → pulserver-0.4.2}/gallery/README.rst +0 -0
  259. {pulserver-0.4.0 → pulserver-0.4.2}/gallery/_gallery_header.md +0 -0
  260. {pulserver-0.4.0 → pulserver-0.4.2}/scripts/build_docs.sh +0 -0
  261. {pulserver-0.4.0 → pulserver-0.4.2}/scripts/check_throughput.py +0 -0
  262. {pulserver-0.4.0 → pulserver-0.4.2}/scripts/format_and_lint.sh +0 -0
  263. {pulserver-0.4.0 → pulserver-0.4.2}/scripts/make_artwork.py +0 -0
  264. {pulserver-0.4.0 → pulserver-0.4.2}/scripts/publish_docs.py +0 -0
  265. {pulserver-0.4.0 → pulserver-0.4.2}/setup.py +0 -0
  266. {pulserver-0.4.0 → pulserver-0.4.2}/src/c/CMakeLists.txt +0 -0
  267. {pulserver-0.4.0 → pulserver-0.4.2}/src/c/core/pulseg_math.c +0 -0
  268. {pulserver-0.4.0 → pulserver-0.4.2}/src/c/include/pulseg/pulseg.h +0 -0
  269. {pulserver-0.4.0 → pulserver-0.4.2}/src/c/include/pulseg/pulseg_cache.h +0 -0
  270. {pulserver-0.4.0 → pulserver-0.4.2}/src/c/include/pulseg/pulseg_config.h +0 -0
  271. {pulserver-0.4.0 → pulserver-0.4.2}/src/c/include/pulseg/pulseg_io.h +0 -0
  272. {pulserver-0.4.0 → pulserver-0.4.2}/src/c/include/pulseg/pulseg_protocol.h +0 -0
  273. {pulserver-0.4.0 → pulserver-0.4.2}/src/c/include/pulseq/pulseq.h +0 -0
  274. {pulserver-0.4.0 → pulserver-0.4.2}/src/c/include/pulseq/pulseq_config.h +0 -0
  275. {pulserver-0.4.0 → pulserver-0.4.2}/src/c/io/pulseg_opts.c +0 -0
  276. {pulserver-0.4.0 → pulserver-0.4.2}/src/c/io/pulseg_protocol.c +0 -0
  277. {pulserver-0.4.0 → pulserver-0.4.2}/src/c/pulseq/pulseq_internal.h +0 -0
  278. {pulserver-0.4.0 → pulserver-0.4.2}/src/c/pulseq/pulseq_shape.c +0 -0
  279. {pulserver-0.4.0 → pulserver-0.4.2}/src/c/structure/pulseg_waves.c +0 -0
  280. {pulserver-0.4.0 → pulserver-0.4.2}/src/cpp/fourier/bindings.cpp +0 -0
  281. {pulserver-0.4.0 → pulserver-0.4.2}/src/cpp/fourier/bindings.hpp +0 -0
  282. {pulserver-0.4.0 → pulserver-0.4.2}/src/cpp/fourier/parallel.hpp +0 -0
  283. {pulserver-0.4.0 → pulserver-0.4.2}/src/cpp/fourier/timeline.cpp +0 -0
  284. {pulserver-0.4.0 → pulserver-0.4.2}/src/cpp/fourier/timeline.hpp +0 -0
  285. {pulserver-0.4.0 → pulserver-0.4.2}/src/cpp/ir/from_libraries.cpp +0 -0
  286. {pulserver-0.4.0 → pulserver-0.4.2}/src/cpp/ir/from_libraries.hpp +0 -0
  287. {pulserver-0.4.0 → pulserver-0.4.2}/src/cpp/ir/pulseq_file.cpp +0 -0
  288. {pulserver-0.4.0 → pulserver-0.4.2}/src/cpp/ir/pulseq_file.h +0 -0
  289. {pulserver-0.4.0 → pulserver-0.4.2}/src/cpp/ir/wave_plan.cpp +0 -0
  290. {pulserver-0.4.0 → pulserver-0.4.2}/src/cpp/ir/waves.cpp +0 -0
  291. {pulserver-0.4.0 → pulserver-0.4.2}/src/cpp/native.hpp +0 -0
  292. {pulserver-0.4.0 → pulserver-0.4.2}/src/cpp/playout.hpp +0 -0
  293. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/__init__.py +0 -0
  294. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_accelerators.py +0 -0
  295. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_cli.py +0 -0
  296. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_labels.py +0 -0
  297. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_logs.py +0 -0
  298. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_memory.py +0 -0
  299. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/__init__.py +0 -0
  300. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/_evaluation.py +0 -0
  301. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/_inversion.py +0 -0
  302. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/_pmc.py +0 -0
  303. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/_saturation.py +0 -0
  304. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/_slab.py +0 -0
  305. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/recon/epi.py +0 -0
  306. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/recon/nufft_train.py +0 -0
  307. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/recon/pics_train.py +0 -0
  308. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/recon/pmc.py +0 -0
  309. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/sequences/bssfp3d.py +0 -0
  310. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/sequences/epi2d.py +0 -0
  311. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/sequences/epi3d.py +0 -0
  312. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/sequences/gre2d.py +0 -0
  313. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/sequences/gre_propeller2d.py +0 -0
  314. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/sequences/gre_radial2d.py +0 -0
  315. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/sequences/gre_stack_of_blades3d.py +0 -0
  316. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/sequences/gre_stack_of_stars3d.py +0 -0
  317. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/sequences/se2d.py +0 -0
  318. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/sequences/se_epi_propeller2d.py +0 -0
  319. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/sequences/se_propeller2d.py +0 -0
  320. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/sequences/se_radial2d.py +0 -0
  321. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/sequences/se_stack_of_blades3d.py +0 -0
  322. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/_zoo/sequences/se_stack_of_stars3d.py +0 -0
  323. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/design/_rf.py +0 -0
  324. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/host/__init__.py +0 -0
  325. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/host/__main__.py +0 -0
  326. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/host/_blocks.py +0 -0
  327. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/host/_push.py +0 -0
  328. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/ir/_checks.py +0 -0
  329. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/ir/_vendor.py +0 -0
  330. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/mrd/__init__.py +0 -0
  331. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/mrd/_acquisitions.py +0 -0
  332. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/mrd/_header.py +0 -0
  333. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/mrd/_images.py +0 -0
  334. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/mrd/_metadata.py +0 -0
  335. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/mrd/_sequence.py +0 -0
  336. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/protocol/__init__.py +0 -0
  337. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/protocol/_keys.py +0 -0
  338. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/protocol/_prescription.py +0 -0
  339. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/protocol/_schema.py +0 -0
  340. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/proxy/__init__.py +0 -0
  341. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/proxy/__main__.py +0 -0
  342. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/proxy/_held.py +0 -0
  343. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/proxy/_intake.py +0 -0
  344. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/proxy/_local.py +0 -0
  345. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/proxy/_queue.py +0 -0
  346. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/proxy/_workers.py +0 -0
  347. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/recon/__init__.py +0 -0
  348. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/recon/__main__.py +0 -0
  349. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/recon/_buffers.py +0 -0
  350. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/recon/_calibration.py +0 -0
  351. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/recon/_exam_image.py +0 -0
  352. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/recon/_figure.py +0 -0
  353. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/recon/_loader.py +0 -0
  354. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/recon/_replay.py +0 -0
  355. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/recon/_runtime/__init__.py +0 -0
  356. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/recon/_runtime/application.py +0 -0
  357. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/recon/_runtime/concurrency.py +0 -0
  358. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/recon/_runtime/connection.py +0 -0
  359. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/recon/_runtime/constants.py +0 -0
  360. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/recon/_runtime/exam.py +0 -0
  361. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/recon/_runtime/readers.py +0 -0
  362. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/recon/_runtime/writers.py +0 -0
  363. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/recon/_units.py +0 -0
  364. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/recon/gadgets.py +0 -0
  365. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/recon/handlers/__init__.py +0 -0
  366. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/recon/handlers/epi.py +0 -0
  367. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/recon/handlers/nufft_train.py +0 -0
  368. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/recon/handlers/pics_train.py +0 -0
  369. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/recon/handlers/pmc.py +0 -0
  370. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/recon/plugin.py +0 -0
  371. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/validate/__init__.py +0 -0
  372. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/validate/_command.py +0 -0
  373. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/validate/_compare.py +0 -0
  374. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/validate/_validate.py +0 -0
  375. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/validate/_xml.py +0 -0
  376. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/virtual/__init__.py +0 -0
  377. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/virtual/_brainweb.py +0 -0
  378. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/virtual/_client.py +0 -0
  379. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/virtual/_coils.py +0 -0
  380. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/virtual/_command.py +0 -0
  381. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/virtual/_export.py +0 -0
  382. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/virtual/_girf.py +0 -0
  383. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/virtual/_localizer.py +0 -0
  384. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/virtual/_motion.py +0 -0
  385. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/virtual/_phantom.py +0 -0
  386. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/virtual/_stream.py +0 -0
  387. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/virtual/_timeline.py +0 -0
  388. {pulserver-0.4.0 → pulserver-0.4.2}/src/pulserver/virtual/_tissue.py +0 -0
  389. {pulserver-0.4.0 → pulserver-0.4.2}/tests/_analytic.py +0 -0
  390. {pulserver-0.4.0 → pulserver-0.4.2}/tests/_seqtext.py +0 -0
  391. {pulserver-0.4.0 → pulserver-0.4.2}/tests/_synthetic.py +0 -0
  392. {pulserver-0.4.0 → pulserver-0.4.2}/tests/_virtual.py +0 -0
  393. {pulserver-0.4.0 → pulserver-0.4.2}/tests/_zoo.py +0 -0
  394. {pulserver-0.4.0 → pulserver-0.4.2}/tests/conftest.py +0 -0
  395. {pulserver-0.4.0 → pulserver-0.4.2}/tests/fixtures/bloch/bssfp.npy +0 -0
  396. {pulserver-0.4.0 → pulserver-0.4.2}/tests/fixtures/bloch/epi_2d_main.npy +0 -0
  397. {pulserver-0.4.0 → pulserver-0.4.2}/tests/fixtures/bloch/gre_2d_3sl.npy +0 -0
  398. {pulserver-0.4.0 → pulserver-0.4.2}/tests/fixtures/bloch/steady_dess_hard_0hz.npy +0 -0
  399. {pulserver-0.4.0 → pulserver-0.4.2}/tests/fixtures/bloch/steady_dess_hard_30hz.npy +0 -0
  400. {pulserver-0.4.0 → pulserver-0.4.2}/tests/fixtures/bloch/steady_echo_hard_0hz.npy +0 -0
  401. {pulserver-0.4.0 → pulserver-0.4.2}/tests/fixtures/bloch/steady_echo_hard_30hz.npy +0 -0
  402. {pulserver-0.4.0 → pulserver-0.4.2}/tests/fixtures/bloch/steady_echo_selective_0hz.npy +0 -0
  403. {pulserver-0.4.0 → pulserver-0.4.2}/tests/fixtures/bloch/steady_fid_hard_0hz.npy +0 -0
  404. {pulserver-0.4.0 → pulserver-0.4.2}/tests/fixtures/sequences/dedup_gre_pair.seq +0 -0
  405. {pulserver-0.4.0 → pulserver-0.4.2}/tests/fixtures/sequences/dedup_gre_pair_b.seq +0 -0
  406. {pulserver-0.4.0 → pulserver-0.4.2}/tests/fixtures/sequences/gre_2d_3sl.seq +0 -0
  407. {pulserver-0.4.0 → pulserver-0.4.2}/tests/koma/Project.toml +0 -0
  408. {pulserver-0.4.0 → pulserver-0.4.2}/tests/koma/simulate.jl +0 -0
  409. {pulserver-0.4.0 → pulserver-0.4.2}/tests/native/check_initializers.c +0 -0
  410. {pulserver-0.4.0 → pulserver-0.4.2}/tests/native/print_wave_samples.c +0 -0
  411. {pulserver-0.4.0 → pulserver-0.4.2}/tests/native/read_rf_definitions.c +0 -0
  412. {pulserver-0.4.0 → pulserver-0.4.2}/tests/native/read_rf_timing.c +0 -0
  413. {pulserver-0.4.0 → pulserver-0.4.2}/tests/native/replay_an_instance.c +0 -0
  414. {pulserver-0.4.0 → pulserver-0.4.2}/tests/plugins/crash.py +0 -0
  415. {pulserver-0.4.0 → pulserver-0.4.2}/tests/plugins/gre2d.py +0 -0
  416. {pulserver-0.4.0 → pulserver-0.4.2}/tests/plugins/gre2d_raw.py +0 -0
  417. {pulserver-0.4.0 → pulserver-0.4.2}/tests/plugins/rf_train.py +0 -0
  418. {pulserver-0.4.0 → pulserver-0.4.2}/tests/plugins/stall.py +0 -0
  419. {pulserver-0.4.0 → pulserver-0.4.2}/tests/plugins/strong.py +0 -0
  420. {pulserver-0.4.0 → pulserver-0.4.2}/tests/plugins/tiny.py +0 -0
  421. {pulserver-0.4.0 → pulserver-0.4.2}/tests/plugins/typed.py +0 -0
  422. {pulserver-0.4.0 → pulserver-0.4.2}/tests/recon/test_app.py +0 -0
  423. {pulserver-0.4.0 → pulserver-0.4.2}/tests/recon/test_buffers.py +0 -0
  424. {pulserver-0.4.0 → pulserver-0.4.2}/tests/recon/test_calibration.py +0 -0
  425. {pulserver-0.4.0 → pulserver-0.4.2}/tests/recon/test_coil_compression.py +0 -0
  426. {pulserver-0.4.0 → pulserver-0.4.2}/tests/recon/test_connection.py +0 -0
  427. {pulserver-0.4.0 → pulserver-0.4.2}/tests/recon/test_epi.py +0 -0
  428. {pulserver-0.4.0 → pulserver-0.4.2}/tests/recon/test_exam_image.py +0 -0
  429. {pulserver-0.4.0 → pulserver-0.4.2}/tests/recon/test_flags.py +0 -0
  430. {pulserver-0.4.0 → pulserver-0.4.2}/tests/recon/test_gadgets.py +0 -0
  431. {pulserver-0.4.0 → pulserver-0.4.2}/tests/recon/test_handlers.py +0 -0
  432. {pulserver-0.4.0 → pulserver-0.4.2}/tests/recon/test_images.py +0 -0
  433. {pulserver-0.4.0 → pulserver-0.4.2}/tests/recon/test_loader.py +0 -0
  434. {pulserver-0.4.0 → pulserver-0.4.2}/tests/recon/test_pmc.py +0 -0
  435. {pulserver-0.4.0 → pulserver-0.4.2}/tests/recon/test_prewhiten.py +0 -0
  436. {pulserver-0.4.0 → pulserver-0.4.2}/tests/recon/test_readers_writers.py +0 -0
  437. {pulserver-0.4.0 → pulserver-0.4.2}/tests/recon/test_slots.py +0 -0
  438. {pulserver-0.4.0 → pulserver-0.4.2}/tests/recon/test_units.py +0 -0
  439. {pulserver-0.4.0 → pulserver-0.4.2}/tests/recon_plugins/children.py +0 -0
  440. {pulserver-0.4.0 → pulserver-0.4.2}/tests/recon_plugins/crash.py +0 -0
  441. {pulserver-0.4.0 → pulserver-0.4.2}/tests/recon_plugins/device.py +0 -0
  442. {pulserver-0.4.0 → pulserver-0.4.2}/tests/recon_plugins/exam.py +0 -0
  443. {pulserver-0.4.0 → pulserver-0.4.2}/tests/recon_plugins/gre2d.py +0 -0
  444. {pulserver-0.4.0 → pulserver-0.4.2}/tests/recon_plugins/pose.py +0 -0
  445. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_console.py +0 -0
  446. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_design_push.py +0 -0
  447. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_design_server.py +0 -0
  448. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_docs.py +0 -0
  449. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_docstring_defaults.py +0 -0
  450. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_docstrings.py +0 -0
  451. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_enrich.py +0 -0
  452. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_exam_artifacts.py +0 -0
  453. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_exam_calibration.py +0 -0
  454. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_exam_sharing.py +0 -0
  455. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_host_slots.py +0 -0
  456. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_image.py +0 -0
  457. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_ir_checks.py +0 -0
  458. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_ir_designed.py +0 -0
  459. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_ir_extensions.py +0 -0
  460. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_ir_labels.py +0 -0
  461. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_ir_profile.py +0 -0
  462. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_ir_repetition.py +0 -0
  463. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_ir_segments.py +0 -0
  464. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_ir_source.py +0 -0
  465. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_ir_steady_excitation.py +0 -0
  466. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_ir_vendor.py +0 -0
  467. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_ir_waves.py +0 -0
  468. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_keys.py +0 -0
  469. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_koma.py +0 -0
  470. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_logs.py +0 -0
  471. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_memory.py +0 -0
  472. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_mrd_images.py +0 -0
  473. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_mrd_sequence.py +0 -0
  474. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_plugins.py +0 -0
  475. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_protocol.py +0 -0
  476. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_publish_docs.py +0 -0
  477. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_resolution.py +0 -0
  478. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_rf_layout.py +0 -0
  479. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_scan_command.py +0 -0
  480. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_seqdesc.py +0 -0
  481. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_sequence_plugin.py +0 -0
  482. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_smoke.py +0 -0
  483. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_validate.py +0 -0
  484. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_virtual.py +0 -0
  485. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_virtual_brainweb.py +0 -0
  486. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_virtual_clock.py +0 -0
  487. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_virtual_coils.py +0 -0
  488. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_virtual_export.py +0 -0
  489. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_virtual_localizer.py +0 -0
  490. {pulserver-0.4.0 → pulserver-0.4.2}/tests/test_virtual_sequences.py +0 -0
@@ -28,7 +28,7 @@ pybind11_add_module(_ext
28
28
  ${CMAKE_SOURCE_DIR}/src/cpp/ir/collection.cpp
29
29
  ${CMAKE_SOURCE_DIR}/src/cpp/ir/waves.cpp
30
30
  ${CMAKE_SOURCE_DIR}/src/cpp/ir/wave_plan.cpp
31
- ${CMAKE_SOURCE_DIR}/src/cpp/ir/repetition.cpp
31
+ ${CMAKE_SOURCE_DIR}/src/cpp/ir/gradient_stretch.cpp
32
32
  ${CMAKE_SOURCE_DIR}/src/cpp/fourier/bindings.cpp
33
33
  ${CMAKE_SOURCE_DIR}/src/cpp/fourier/timeline.cpp
34
34
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pulserver
3
- Version: 0.4.0
3
+ Version: 0.4.2
4
4
  Summary: Orchestrator for MR acquisitions: sequence design, scanner preparation and reconstruction.
5
5
  Keywords: mri,pulseq,mrd,ismrmrd,reconstruction,scanner
6
6
  Author-Email: Matteo Cencini <matteo.cencini@gmail.com>
@@ -21,22 +21,21 @@ Project-URL: Documentation, https://pulserver.github.io/pulserver/
21
21
  Project-URL: Issues, https://github.com/pulserver/pulserver/issues
22
22
  Project-URL: Source, https://github.com/pulserver/pulserver
23
23
  Requires-Python: >=3.10
24
- Requires-Dist: pypulseqpp>=0.0.42
24
+ Requires-Dist: pypulseqpp>=0.0.46
25
25
  Requires-Dist: numpy>=2.2.6
26
26
  Requires-Dist: ismrmrd>=1.15.0
27
27
  Requires-Dist: pydicom>=3.0.2
28
28
  Requires-Dist: torch>=2.4
29
29
  Requires-Dist: blochsim>=0.0.12
30
- Requires-Dist: bartorch>=0.0.14
30
+ Requires-Dist: bartorch>=0.0.17
31
31
  Requires-Dist: brainweb-dl>=0.4.6
32
32
  Requires-Dist: websockets>=16.1.1
33
- Requires-Dist: tomli>=2.0.1; python_version < "3.11"
34
33
  Provides-Extra: dev
35
34
  Requires-Dist: pytest>=9.1.1; extra == "dev"
36
35
  Requires-Dist: pytest-cov>=7.1.0; extra == "dev"
37
36
  Requires-Dist: pytest-xdist>=3; extra == "dev"
38
37
  Requires-Dist: coverage>=7.16.2; extra == "dev"
39
- Requires-Dist: ruff==0.17.0; extra == "dev"
38
+ Requires-Dist: ruff==0.17.1; extra == "dev"
40
39
  Requires-Dist: pre-commit>=4.6.2; extra == "dev"
41
40
  Requires-Dist: build; extra == "dev"
42
41
  Provides-Extra: doc
@@ -28,17 +28,16 @@ control variable, are described in {doc}`../explanations/protocol`.
28
28
 
29
29
  ## Options
30
30
 
31
- A plugin's options are module constants a parameter file sets when the plugin
32
- is loaded, so that they shape its sequence function and the protocol it
33
- declares. A design call selects the file by number: set `N` of a plugin whose
34
- file is `<script>.py` is `parameters/<script>/<NN>.toml`, and set 0 loads the
35
- plugin with its defaults.
31
+ A plugin's options are module constants that shape its sequence function and
32
+ the protocol it declares. Each is a user entry holding the index of its value
33
+ among its choices, and a design call loads the plugin at the options its
34
+ request states ({ref}`plugin-options`).
36
35
 
37
36
  | Object | Description |
38
37
  | --- | --- |
39
- | {obj}`~pulserver.design.option` | The value of an option: the parameter file's, else its default. |
40
- | {obj}`~pulserver.design.read_options` | The options a parameter file sets. |
41
- | {obj}`~pulserver.design.OptionError` | An option a parameter file sets that the plugin does not declare or take. |
38
+ | {obj}`~pulserver.design.option` | Declare an option at a user entry; the value the plugin is loaded with. |
39
+ | {obj}`~pulserver.design.OptionParam` | The entry an option is listed as: the index of its value among its choices. |
40
+ | {obj}`~pulserver.design.OptionError` | An option a plugin is loaded with that it does not declare or take, or a declaration the console cannot list. |
42
41
 
43
42
  ## RF layout
44
43
 
@@ -40,7 +40,8 @@ the cache layout in {doc}`../developer-guide/internals/ir-cache`.
40
40
  | {obj}`~pulserver.ir.Format` | Whether a quantity is stored as a float in its SI unit or as an integer. |
41
41
  | {obj}`~pulserver.ir.sample_wave` | A cache's wave on a playout's gradient raster, as loaded into a region of its waveform memory. |
42
42
  | {obj}`~pulserver.ir.playout` | Both stages of a segmented playout of a cache, the scan or its receive-gain prescan, recorded: what each position prepares, the registers of each block, what each wave reads from waveform memory and, on request, the waveforms each block plays. |
43
- | {obj}`~pulserver.ir.Prescan` | The receive-gain calibration a playout plays instead of the scan: one subsequence, to the instance completing its readouts. |
44
- | {obj}`~pulserver.ir.repetition_gradients` | The gradients of a subsequence's repetition of most gradient energy, as corner points and on a raster: what a scanner's heating and acoustic models are evaluated on. |
43
+ | {obj}`~pulserver.ir.Prescan` | The receive-gain calibration a playout plays instead of the scan: one subsequence, to the instance completing its readouts, opened by the pTx tour on request. |
44
+ | {obj}`~pulserver.ir.prescan_tour` | The pTx prescan tour of a cache: the segment instance holding each channel's largest drive of every parallel-transmit RF definition. |
45
+ | {obj}`~pulserver.ir.gradient_stretch` | The gradients of a subsequence's hyper-repetition-long stretch of most gradient energy, or of the one from its heaviest repetition, as corner points and on a raster: what a scanner's heating model is evaluated on. |
45
46
  | {obj}`~pulserver.ir.chain` | Files of the `NextSequence` chain starting at a sequence file, in play order. |
46
47
  | {obj}`~pulserver.ir.cache_path` | Cache file of a sequence file. |
@@ -7,7 +7,7 @@ authors.
7
7
  | Page | Contents |
8
8
  | --- | --- |
9
9
  | {doc}`calibration` | Prewhitening, coil compression, sensitivity maps and the reuse of stored maps |
10
- | {doc}`ir-cache` | Conversion passes, waves, playout stages, the heaviest repetition, the cache file and the C89 library |
10
+ | {doc}`ir-cache` | Conversion passes, waves, playout stages, the gradient stretches, the cache file and the C89 library |
11
11
  | {doc}`protocol-wire` | RF layout, protocol keys and values, and the protocol text blocks |
12
12
  | {doc}`reconstruction-proxy` | Reconstruction units, image headers, enrichment and trajectory rules, readout placement and workers |
13
13
  | {doc}`sar-ratios` | pTx SAR ratios from VOPs against a reference pulse |
@@ -95,8 +95,8 @@ the chain is read. RF and ADC frequency and phase offsets are stored absolute:
95
95
  the ppm offsets are resolved on the host, at the gamma and B0 of the call's
96
96
  limits, by pypulseqpp's `SequenceLibraries.absolute_offsets`. The labels
97
97
  and flags in force at each block, with `PMC` in force from the first, are
98
- pypulseqpp's `Sequence.evaluate_labels`, and a `TRID` group starts at each block
99
- `Sequence.label_blocks` lists as setting it; the rotation and RF shim a block
98
+ pypulseqpp's `Sequence.evaluate_labels`, and the blocks that set `TRID` are
99
+ those `Sequence.label_blocks` lists; the rotation and RF shim a block
100
100
  plays are `Sequence.block_rotations` and `Sequence.block_shims`. A segment
101
101
  position records whether the scanner may move its excitation at run time by a
102
102
  carrier offset alone: every instance plays its RF pulse under one gradient,
@@ -200,10 +200,35 @@ instance.
200
200
 
201
201
  The receive-gain calibration prescan plays one subsequence from its start to
202
202
  the segment instance that completes the readouts its sequence declares
203
- (`NumGainCalibrationReadouts`, at least one). It waits for no trigger and
203
+ (`NumGainCalibrationReadouts`). A readout whose block carries the `NOPRESCAN`
204
+ label plays without being acquired and is not counted, so a multi-echo
205
+ sequence calibrates on its first echo. The count ends with a repetition, so the gain
206
+ is set on whole repetitions of the scan; the conversion refuses one that ends
207
+ inside a repetition, and takes the readouts through the first repetition that
208
+ acquires when the sequence declares none. It waits for no trigger and
204
209
  drives no digital output, and every gradient whose amplitude varies across
205
210
  repetitions, a phase encoding for instance, plays at zero, as does a wave any
206
- of whose logical axes varies.
211
+ of whose logical axes varies. An RF pulse whose frequency offset varies across
212
+ repetitions, the slices of a stack, plays at the mean offset over them, as a
213
+ scanner calibrates on one slice. Both are kept per position within the
214
+ repetition, as the gradient flags are, and reported on the block instance
215
+ (`rf_freq_variable` and `rf_freq_mean_hz`). The offsets are those of the
216
+ cache, the field-of-view offset included, so the mean is the centre of the
217
+ positioned stack.
218
+
219
+ A parallel-transmit sequence can open its prescan with the pTx tour
220
+ (`pulseg_get_prescan_tour`): for every channel of every parallel-transmit RF
221
+ definition of every subsequence, the segment instance holding the largest
222
+ drive that channel receives, the RF amplitude times the channel's shim
223
+ magnitude, or the amplitude alone for a pulse with a waveform per channel.
224
+ Each instance is visited once, under the prescan's rules, whether or not it
225
+ reads out; the tour either acquires its readouts, counted on top of the
226
+ calibration's, or plays them unacquired. A playout reaches each visit by
227
+ seeking the cursor to its first block (`pulseg_cursor_seek`). A visit plays
228
+ part of one occurrence of its subsequence's repetition, each pulse at its
229
+ largest, so resting after it until it has lasted the time per occurrence the
230
+ scan's RF is costed at keeps its average power within the scan's; the rest is
231
+ the interpreter's, from the visit's duration.
207
232
 
208
233
  Waveform memory holds samples of the type and scale a scanner build defines
209
234
  before it includes the library: `PULSEG_WAVE_SAMPLE`, the type;
@@ -229,29 +254,43 @@ to that type.
229
254
 
230
255
  ## Heaviest repetition
231
256
 
232
- A scanner evaluates its gradient-heating model on the gradients of a
233
- repetition, and the host's sound pressure check
234
- (`pypulseqpp.safety.check_spl`) chooses the same one. For each subsequence,
235
- the conversion finds the repetition, of those the execution stream holds from
236
- its first block, over which
257
+ A scanner evaluates its gradient-heating model on the gradients of two
258
+ stretches of each subsequence, each as if played without end against its own
259
+ duration ({func}`~pulserver.ir.gradient_stretch`,
260
+ `pulseg_get_gradient_stretch`). A stretch is the run of whole segment instances
261
+ from one instance's start until they last the subsequence's hyper-repetition,
262
+ or `PULSEG_STRETCH_US`, 10 s, where that is shorter, or to the subsequence's end
263
+ where it comes first, each block at its played duration, a pure delay at its
264
+ instance's. The hyper-repetition is the shortest run of repetitions whose
265
+ durations repeat over the whole subsequence, a last run cut short allowed
266
+ (`hyper_copies` and `hyper_us` of `pulseg_get_tr_timing`, from the prefix
267
+ function of the repetitions' durations in us): one repetition where all last
268
+ the same, five for a five-slice packet whose last slice carries the pad, all of
269
+ them where they do not repeat. Where it is one repetition, the second stretch
270
+ is the heaviest repetition itself.
271
+
272
+ | Stretch | Start |
273
+ |---|---|
274
+ | `PULSEG_STRETCH_HEAVIEST` | Of the instance starts whose stretch lasts that long, the one of largest $E$, the earliest on a tie; the subsequence's start where none does |
275
+ | `PULSEG_STRETCH_HEAVIEST_REPETITION` | The instance holding the start of the repetition of largest $E$, of those the execution stream holds from its first block, the earliest on a tie |
237
276
 
238
277
  $$
239
278
  E = \int \lVert \mathbf{g}(t) \rVert^2 \, dt
240
279
  $$
241
280
 
242
- is largest, the earliest on a tie, or the whole subsequence where it does not
243
- repeat, and the cache carries its gradients
244
- ({func}`~pulserver.ir.repetition_gradients`, `pulseg_get_tr_corner_points`).
245
- $E$ sums, over the blocks and their gradient events, the square of each
246
- event's amplitude times the integral of its normalised waveform's square, which a rotation leaves unchanged, so the choice
247
- does not depend on the blocks' rotations. The repetition is one the scanner
248
- plays, each block at its own amplitudes and with its own shapes and rotation,
249
- or through its wave: a waveform that plays, not an envelope of
250
- several. Its gradients are joined over its blocks as corner points on one
251
- timeline, along the logical axes and linear in between; the prescription's
252
- rotation takes them to the physical axes, and a model that needs them on a
253
- raster samples them at the centres of its intervals
254
- (`pulseg_sample_corner_points`).
281
+ sums, over the blocks and their gradient events, the square of each event's
282
+ amplitude times the integral of its normalised waveform's square, which a
283
+ rotation leaves unchanged, so neither choice depends on the blocks' rotations.
284
+ The first stretch is found by sliding its end ahead of its start over the
285
+ instances, each walk passing over the stream once. The second holds a short
286
+ burst the first averages out; the host's sound pressure check
287
+ (`pypulseqpp.safety.check_spl`) chooses the same repetition. Each block plays
288
+ at its own amplitudes and with its own shapes and rotation, or through its
289
+ wave: a waveform that plays, not an envelope of several. The gradients are
290
+ joined over the blocks as corner points on one timeline, along the logical
291
+ axes and linear in between; the prescription's rotation takes them to the
292
+ physical axes, and a model that needs them on a raster samples them at the
293
+ centres of its intervals (`pulseg_sample_corner_points`).
255
294
 
256
295
  ## Cache file
257
296
 
@@ -259,7 +298,7 @@ The cache has the name of the first sequence file with its extension replaced,
259
298
  `.pseg` by default. It is divided into sections that a consumer loads
260
299
  independently. The pulse-generation stage of a playout reads the
261
300
  definitions, their waveforms, the waves and their layout, and the gradients of
262
- each subsequence's heaviest repetition; the scan loop also reads
301
+ each subsequence's stretches; the scan loop also reads
263
302
  the per-block instances, the rotations and the execution stream, whose size
264
303
  scales with the scan length. Integer and float fields are 4 bytes. The byte
265
304
  order is recorded in the file, and a reader on a machine of the other byte order swaps on load. A
@@ -289,7 +328,7 @@ playout to the cursor's, bit for bit.
289
328
 
290
329
  The IR is built by C++ passes in `src/cpp/ir/`, which run only on the host:
291
330
  the segmentation, the waves, their layout in a playout's waveform memory and
292
- each subsequence's heaviest repetition. The cache reader and writer, the
331
+ each subsequence's stretches. The cache reader and writer, the
293
332
  accessors a playout uses to walk the loaded collection, and the two stages of a
294
333
  playout are compiled into the interpreter, whose vendor toolchains accept ANSI
295
334
  C. They are therefore C89, in `src/c/`, and call nothing in `src/cpp/`. The
@@ -96,6 +96,20 @@ imaging_mode: stringlist|1|2d|3d
96
96
  A value block carries `name: value` lines only, a string list as the index of
97
97
  its chosen option.
98
98
 
99
+ An option ({ref}`plugin-options`) is an integer user entry, the index of its
100
+ choice. Its mode, `dropdown` with the indices as options (`0|1` for a flag),
101
+ marks it as an option; an interpreter shows it as a number, like any user entry:
102
+
103
+ ```text
104
+ user36_value: int|dropdown|0|0|1|1||0|1
105
+ user36_name: description|Navigator: 0 off, 1 on
106
+ ```
107
+
108
+ A `list` call reads only the option entries of the value block it is given, and
109
+ lists the plugin at those options; `validate` and `generate` load the plugin at
110
+ the options of their request before reading the rest of it against that
111
+ listing. An interpreter lists the plugin again when an option entry changes.
112
+
99
113
  The RF blocks follow a reply when the call asks for them, and no block follows
100
114
  where the evaluation is invalid or states no layout. They are lists of numbers:
101
115
  each number is ASCII decimal with nine significant digits, the numbers of a list
@@ -188,10 +188,17 @@ arrives, and replayed to a worker once a slot is released. The client remains
188
188
  connected meanwhile, and the images are returned through its connection.
189
189
 
190
190
  Images, DICOM datasets and text produced by the worker are relayed to the
191
- client as they are produced. Closing either connection closes the other. Once
192
- the client's stream ends, the proxy waits for the worker to close however long
193
- the reconstruction takes, unless it was started with a reconstruction timeout,
194
- past which the worker is terminated and the client told so.
191
+ client as they are produced once the client's stream has ended whole, with its
192
+ `CLOSE` or a last acquisition flagged `LAST_IN_MEASUREMENT`; what the worker
193
+ produces before, such as a unit that closes on the last readout, is held until
194
+ then. A stream that ends otherwise is refused and the held output dropped, so a
195
+ scan the scanner stopped after its last readout returns nothing. A worker that
196
+ stops reading, as one whose plugin failed, has the rest of the stream read and
197
+ dropped, so what it said reaches the client of a whole stream. Closing either
198
+ connection closes the other. Once the client's stream ends, the proxy waits for
199
+ the worker to close however long the reconstruction takes, unless it was
200
+ started with a reconstruction timeout, past which the worker is terminated and
201
+ the client told so.
195
202
 
196
203
  ## Enrichment
197
204
 
@@ -90,9 +90,9 @@ $$
90
90
  \alpha_j = \alpha\,|b^+(\mathbf{r}_j)|\,P(\mathbf{g}\cdot\mathbf{r}_j + f_j - f_\mathrm{rf}),
91
91
  $$
92
92
 
93
- about its axis turned by the phase of the transmit field $b^+$, relative to
94
- the pulse's nominal amplitude. A pulse played under a gradient that changes
95
- along one direction $\hat{\mathbf{n}}$, as a spectral-spatial pulse's
93
+ with $b^+$ relative to the pulse's nominal amplitude, about its axis turned as
94
+ a pulse phase of $-\arg b^+$ turns it ({ref}`transmit-phase-convention`). A
95
+ pulse played under a gradient that changes along one direction $\hat{\mathbf{n}}$, as a spectral-spatial pulse's
96
96
  alternating lobes do, has a profile in both the field and the position along
97
97
  it, $P(f_j - f_\mathrm{rf}, \hat{\mathbf{n}}\cdot\mathbf{r}_j)$, simulated
98
98
  from its samples under that gradient; a pulse played under no gradient, or
@@ -230,7 +230,8 @@ A pulse plays on every transmit channel, weighted by the coil's default shim,
230
230
  the weights of magnitude $1/\sqrt{N}$ for $N$ channels that bring the channels
231
231
  into phase at the isocentre, where the pulse then has its nominal amplitude:
232
232
  each cube sees the transmit field
233
- $b^+(\mathbf{r}) = \sum_c w_c\,s^+_c(\mathbf{r})$, for the weights $w_c$. The
233
+ $b^+(\mathbf{r}) = \sum_c \overline{w_c}\,s^+_c(\mathbf{r})$, for the weights
234
+ $w_c$, which drive the channels. The
234
235
  squares of the weights sum to 1, so the channels together carry the power of
235
236
  one channel at the pulse's amplitude, and an RF shim is written in the same
236
237
  normalisation: a circularly polarised shim of $N$ channels has weights of
@@ -91,8 +91,8 @@ every block. The *repetition* of a subsequence is the period
91
91
  `pypulseqpp.Sequence.repetition()` reports, the whole subsequence where it
92
92
  does not repeat; the conversion finds virtual segments within it. Do not write
93
93
  "repeating unit", which implies that every sequence is periodic, nor "segment
94
- definition" for a virtual segment. A `TRID` label marks a *safety group* here,
95
- not a segment boundary. The *IR cache* is the file; the *collection* is what a
94
+ definition" for a virtual segment. A `TRID` label is carried with each block
95
+ and places no segment boundary. The *IR cache* is the file; the *collection* is what a
96
96
  reader loads from it.
97
97
 
98
98
  **Virtual scanner.** The stand-ins for the scanner in tests: the *virtual
@@ -99,7 +99,8 @@ designs/
99
99
  manifest.json identity and identifier, limits, package versions,
100
100
  creation time, plugin and source, scan time,
101
101
  field-of-view offset, SHA-256 of every file
102
- motion.buf the poses of a scan corrected for motion
102
+ motion.buf the poses of a scan corrected for motion, created
103
+ empty with its design
103
104
  ```
104
105
 
105
106
  A design is reused while its scan holds it; a design call that resolves to
@@ -29,10 +29,13 @@ on the other end refuses a series it cannot serve, enriches it from its design
29
29
  Code: {class}`~pulserver.proxy.DesignCache`, {class}`~pulserver.proxy.DesignIntake`. Tests: *a design pushed to the intake is reconstructed from its store*; *a series naming no stored design is refused* (`test_proxy.py`).
30
30
  - **Refuses a malformed stream with a text the console shows.**
31
31
 
32
- Code: {class}`~pulserver.proxy.ReconProxy`. Tests: *a series carrying no header or two is refused*; *a series that ends before its last readout is refused*; *a message the proxy cannot read ends the output with its type* (`test_proxy.py`).
33
- - **Reconstructs each series in a fresh worker process, with spares that have already imported the engine.**
32
+ Code: {class}`~pulserver.proxy.ReconProxy`. Tests: *a series carrying no header or two is refused*; *a series that ends before its last readout is refused*; *a message the proxy cannot read ends the output with its type*; *a series carrying a message the proxy cannot read is refused* (`test_proxy.py`).
33
+ - **Returns nothing of a scan whose client ends the stream without a `CLOSE`, though its images were already made.**
34
34
 
35
- Code: {class}`~pulserver.proxy.ReconProxy`. Tests: *the spare worker is replaced after each series*; *the proxy process does not import the reconstruction engine*; *a crashing plugin closes its series and frees the slot* (`test_proxy.py`).
35
+ Code: {class}`~pulserver.proxy.ReconProxy`. Tests: *a scan stopped after its last readout exports nothing* (`test_proxy.py`).
36
+ - **Reconstructs each series in a fresh worker process, with spares that have already imported the engine, and returns why one failed.**
37
+
38
+ Code: {class}`~pulserver.proxy.ReconProxy`. Tests: *the spare worker is replaced after each series*; *the proxy process does not import the reconstruction engine*; *a crashing plugin closes its series and frees the slot*; *a plugin crashing while its series still arrives reports why* (`test_proxy.py`).
36
39
  - **Bounds concurrent series by slots, one per GPU by default, and holds the rest on disk.**
37
40
 
38
41
  Code: `--slots`, `--gpu-slots`, `--queue`. Tests: *a second series waits for a slot and still returns images*; *a series with every slot busy is held on disk until one frees*; *a series reads the gpu its slot holds* (`test_proxy.py`).
@@ -51,9 +54,9 @@ on the other end refuses a series it cannot serve, enriches it from its design
51
54
  - **Publishes the poses of a motion-corrected series to the running scan.**
52
55
 
53
56
  Code: `pulserver.proxy._motion`. Tests: *a motion corrected series publishes its poses to the scan*; *a series not corrected for motion writes no pose file* (`test_proxy.py`).
54
- - **Keeps each series as the scanner sent it, for an offline rerun that gives the same image.**
57
+ - **Keeps each series enriched, for an offline rerun that gives the same image.**
55
58
 
56
- Code: `--save-data`. Tests: *a kept series runs offline and gives the image the proxy returned*; *what a proxy keeps is the header the scanner sent* (`test_proxy.py`).
59
+ Code: `--save-data`. Tests: *a kept series runs offline and gives the image the proxy returned*; *what a proxy keeps is the series it reconstructed, enriched*; *a kept series given its design is not enriched twice* (`test_proxy.py`).
57
60
  - **Holds images for a client that dropped, and closes on its own when idle.**
58
61
 
59
62
  Code: `--idle-timeout`. Tests: *images whose client has gone reach it when it returns*; *the idle timeout counts from the last client leaving* (`test_proxy.py`).
@@ -85,8 +88,10 @@ A series is `CONFIG`, `HEADER`, the `ACQUISITION`s and optional `WAVEFORM`s,
85
88
  then `CLOSE`; what returns is `IMAGE`, `DICOM_WITHNAME` and `TEXT` messages,
86
89
  then `CLOSE`. These are the identifiers of Gadgetron's MRD streaming protocol.
87
90
  A refused series receives one `TEXT` beginning `pulserver:` and a `CLOSE` at
88
- once. An MRD message carries no length, so a message type the proxy cannot
89
- read ends the series.
91
+ once. A stream that ends without its `CLOSE` is a scan that did not finish: it
92
+ is refused, and what its reconstruction produced is not returned. An MRD
93
+ message carries no length, so a message type the proxy cannot read ends the
94
+ series.
90
95
 
91
96
  ### Workers and slots
92
97
 
@@ -91,8 +91,9 @@ converted into the IR cache with its sound pressure levels and SAR ratios.
91
91
 
92
92
  Two logical axes at 0.8 of the amplitude limit put $0.8\sqrt{2}$ of it on one
93
93
  physical axis at 45°. So the sequence is designed under `design_max_grad` and
94
- `design_max_slew`, which the scanner derates for the prescription, and checked
95
- on the physical axes against `max_grad` and `max_slew`. The rotation arrives
94
+ `design_max_slew`, which the scanner derates for the prescription, less the
95
+ design margin of `pypulseqpp.apply_system_derates`, and checked on the physical
96
+ axes against `max_grad` and `max_slew` as sent. The rotation arrives
96
97
  in the protocol's `fov_rotation_ij` entries; your sequence function never sees
97
98
  it.
98
99
 
@@ -177,7 +177,7 @@ Two offsets give two caches, and two designs.
177
177
  | Aspect | PulSeg 2.1-alpha | pulserver |
178
178
  | --- | --- | --- |
179
179
  | Segment-instance boundaries | Marked by the sequence designer with `TRID` labels (§4.2) | Found within the repetition under the {class}`~pulserver.ir.Grouping` |
180
- | `TRID` | Identifies the virtual segment an instance plays | A sticky group, reported to the interpreter's checks with the duration of each occurrence; it places no segment boundary |
180
+ | `TRID` | Identifies the virtual segment an instance plays | Carried with each block; it places no segment boundary |
181
181
  | Periodicity | Not part of the model | Taken from pypulseqpp when present, and used to encode the stream |
182
182
  | Multishot gradient variants | One base block with shot variants, chosen per instance by the optional `gradient_shot_index` | No shot index: a gradient that differs between instances is played as a wave from waveform memory, or the run is a variant of its virtual segment |
183
183
 
@@ -31,12 +31,19 @@ names none, or that sends no config, unless it forwards with a
31
31
  the proxy searches its own `--plugins` directories for that name, whatever the
32
32
  path's directory.
33
33
 
34
- The client then reads until the proxy's `CLOSE`: images (`IMAGE`, 1022),
35
- DICOM datasets (`DICOM_WITHNAME`, 1018) and texts (`TEXT`, 5), in the order the
36
- reconstruction produces them. A text beginning `pulserver:` reports a series
37
- that failed. A refused series receives that text and a `CLOSE` at once; the
38
- proxy then discards what the client still sends until it closes the
39
- connection, so the client can finish sending and read the reason.
34
+ The client then reads until the proxy's `CLOSE`: images (`IMAGE`, 1022), DICOM
35
+ datasets (`DICOM_WITHNAME`, 1018) and texts (`TEXT`, 5), in the order the
36
+ reconstruction produces them. Nothing is returned before the series has ended
37
+ whole, with the client's `CLOSE` or a last acquisition flagged
38
+ `LAST_IN_MEASUREMENT`: a reconstruction may finish on the last readout, and
39
+ what it produces then is held until that end. A text beginning `pulserver:`
40
+ reports a series that failed. A refused series receives that text and a `CLOSE`
41
+ at once; the proxy then discards what the client still sends until it closes
42
+ the connection, so the client can finish sending and read the reason.
43
+
44
+ A client ends a scan the scanner stopped by shutting its side of the connection
45
+ for writing without a `CLOSE`, then reading the reply as usual. The series is
46
+ refused and nothing it produced is returned, even when every readout arrived.
40
47
 
41
48
  ## Header
42
49
 
@@ -107,8 +114,10 @@ noise scans and navigators included, and no other.
107
114
 
108
115
  A series is refused, and its reconstruction stopped, when an acquisition has a
109
116
  sample count other than its readout's, when the scan counters skip or repeat
110
- one, when an acquisition before the last is flagged `LAST_IN_MEASUREMENT`, or
111
- when the stream carries more or fewer acquisitions than the chain plays.
117
+ one, when an acquisition before the last is flagged `LAST_IN_MEASUREMENT`,
118
+ when the stream carries more or fewer acquisitions than the chain plays, or
119
+ when it ends without a `CLOSE` or a last acquisition flagged
120
+ `LAST_IN_MEASUREMENT`.
112
121
 
113
122
  ## See also
114
123
 
@@ -252,6 +252,16 @@ that unit's calibration k-space (its imaging k-space where it has none), and
252
252
  projects every later unit onto it. Compress a unit before requesting its maps,
253
253
  so that they are estimated in the basis of the data they are used with.
254
254
 
255
+ The `pics` and `nufft` handlers fit the maps with
256
+ `apps.nlinv_maps(kspace, phase_pole=0)`, `bart nlinv --phase-pole 0`, on a grid
257
+ of the central 24 lines, or of the trajectory's samples within 12 grid units of
258
+ the centre, and zero-fill them to the image grid: after every Gauss-Newton step
259
+ the phase poles the maps share are moved into the image. Without it, maps that
260
+ share a phase pole go to zero there in every coil, and the image has a dark
261
+ spot at it. BART refuses the detection on a grid with an axis no longer than a
262
+ twentieth of its longest, rounded up; a slab of fewer than 3 partitions is
263
+ fitted without the correction.
264
+
255
265
  A calibration unit, whose `data.data` is `None`, stores its maps for its slice,
256
266
  and the imaging units of that slice take them from the stream. A series that is
257
267
  only a calibration leaves its maps to the exam by assigning
@@ -389,10 +399,12 @@ process ID, level and logger name.
389
399
  ## Offline reconstruction
390
400
 
391
401
  {meth}`~pulserver.recon.ReconPlugin.run` reconstructs an ISMRMRD HDF5 file in
392
- the calling process, through the same hooks. A file recorded as the scanner
393
- sends it, such as `pulserver scan --mrd raw.h5` or the proxy's `--save-data`
394
- writes, is enriched first from the design it was played from, found in a design
395
- store or given as its sequence file, with its manifest beside it:
402
+ the calling process, through the same hooks. A file the proxy's `--save-data`
403
+ keeps is enriched already and plays as it stands. A file recorded as the
404
+ scanner sends it, such as `pulserver scan --mrd raw.h5` writes, is enriched
405
+ first from the design it was played from, found in a design store or given as
406
+ its sequence file, with its manifest beside it; given a design, an enriched
407
+ file is still played as it stands, never enriched twice:
396
408
 
397
409
  ```python
398
410
  images = PLUGIN.run("raw.h5", store="designs")
@@ -435,9 +447,9 @@ volume as one image per partition.
435
447
 
436
448
  | Plugin | Reconstructs |
437
449
  | --- | --- |
438
- | `pics` | One image per slice, contrast, cardiac phase, set and repetition, averages summed, from readouts placed by their encoding counters, whitened, completed to full echoes and cropped to the reconstruction field of view as they arrive (`Prewhiten`, `AsymmetricEcho`, `RemoveReadoutOversampling`). Each image is solved as `bart pics -R W` over the coil sensitivities of {func}`~pulserver.recon.coil_maps` (`bart nlinv` of the unit's calibration readouts, else the maps stored for its slice or the exam's, else a fit to the unit's own low-resolution centre), then completed by `bart homodyne` along a partial-Fourier axis. A unit of calibration readouts only makes no image and stores its maps |
450
+ | `pics` | One image per slice, contrast, cardiac phase, set and repetition, averages summed, from readouts placed by their encoding counters, whitened, completed to full echoes and cropped to the reconstruction field of view as they arrive (`Prewhiten`, `AsymmetricEcho`, `RemoveReadoutOversampling`). Each image is solved as `bart pics -R W` over the coil sensitivities of {func}`~pulserver.recon.coil_maps` (`bart nlinv --phase-pole 0` of the unit's calibration readouts, else the maps stored for its slice or the exam's, else a fit to the unit's own low-resolution centre), then completed by `bart homodyne` along a partial-Fourier axis. A unit of calibration readouts only makes no image and stores its maps |
439
451
  | `pics_train` | `pics`'s images from readouts that number their place in an echo train or an inversion shot (`contrast`, `ECO`), merged so that the readouts of every place fill one image |
440
- | `nufft` | The images of `pics` for a radial, spiral, PROPELLER or zero-echo-time trajectory or a stack of them, each solved as `bart pics -t -R W` over `bart nlinv -t` sensitivities of the unit's samples near the k-space centre. The readouts of every segment of a unit, the blades of a PROPELLER scan or the shells of a zero-echo-time one, enter one solve; a trajectory that encodes the partition direction without a partition axis is solved as one volume |
452
+ | `nufft` | The images of `pics` for a radial, spiral, PROPELLER or zero-echo-time trajectory or a stack of them, each solved as `bart pics -t -R W` over `bart nlinv --phase-pole 0 -t` sensitivities of the unit's samples near the k-space centre. The readouts of every segment of a unit, the blades of a PROPELLER scan or the shells of a zero-echo-time one, enter one solve; a trajectory that encodes the partition direction without a partition axis is solved as one volume |
441
453
  | `nufft_train` | `nufft`'s images from readouts that number their place in a train of excitations (`contrast`, `ECO`), merged so that the readouts of every place fill one image |
442
454
  | `epi` | `pics`'s images from EPI readouts, each whitened, resampled off its ramps onto the matrix and corrected for its odd/even phase against the shot's navigator as it arrives (`bart` ramp operator, `estimate_epi_phase`). The phase-encode-reversed reference set is an image of its own; with PyHySCO installed (GPL-3.0, not a dependency; the Docker image carries it), each later image of its slice, or volume of a 3D scan, is corrected for susceptibility distortion against it |
443
455
  | `pmc` | `pics_train`'s images, and a pose from each three-plane navigator (`NAV` or `RTFEEDBACK` readouts): planes gridded with Pipe-Menon density compensation on one thread, coils combined by root sum of squares, registered against the first navigator and filtered by an extended Kalman filter. The pose is published to the scan when its design sets `EnablePmc` |
@@ -17,7 +17,7 @@ store are described in {doc}`../explanations/architecture`.
17
17
  ## Design calls
18
18
 
19
19
  ```bash
20
- pulserver design list --plugins DIR --plugin NAME [--limits FILE --rf-definitions] [--socket PATH]
20
+ pulserver design list --plugins DIR --plugin NAME [--values FILE] [--limits FILE --rf-definitions] [--socket PATH]
21
21
  pulserver design validate --plugins DIR --plugin NAME --limits FILE [--rf-layout] [--exam DIR] [--socket PATH] < VALUES
22
22
  pulserver design generate --plugins DIR --plugin NAME --limits FILE --store DIR --scan NAME [--exam DIR] [--push URL] [--socket PATH] < VALUES
23
23
  pulserver design import --limits FILE --store DIR --scan NAME [--push URL] [--socket PATH] < IMPORT
@@ -36,7 +36,7 @@ directory name, not starting with `.`.
36
36
 
37
37
  | Call | Reply |
38
38
  | --- | --- |
39
- | `list` | `PROTOCOL` and the plugin's listing block; with `--rf-definitions`, the `[RfDefinitions]` block |
39
+ | `list` | `PROTOCOL` and the plugin's listing block at the options of the value block in `--values` ({ref}`plugin-options`); with `--rf-definitions`, the `[RfDefinitions]` block |
40
40
  | `validate` | `VALID <seconds>` or `INVALID`, an `INFO` line and the value block of the resolved protocol; with `--rf-layout`, a valid reply ends with the `[RfLayout]` block |
41
41
  | `generate` | `GENERATED <id>`, the identifier of the design in the scan's directory |
42
42
  | `import` | `IMPORTED <id>` |
@@ -53,9 +53,9 @@ evaluation states an RF layout ({ref}`stating-the-rf-layout`).
53
53
  `--rf-definitions` evaluates the plugin at its default protocol under
54
54
  `--limits`, which it then requires. `--rf-layout` follows a valid reply with the
55
55
  RF layout of the evaluated request, its amplitudes relative to the peaks the
56
- listing states. Without `--rf-definitions`, `list` depends on the plugin file
57
- and the installed packages only, so its reply can be written once at
58
- installation and read without a call.
56
+ listing states. Without `--rf-definitions`, `list` depends on the plugin file,
57
+ its options and the installed packages only, so its reply can be written once
58
+ at installation and read without a call.
59
59
 
60
60
  `--exam` names the directory of the current exam's cache, which is passed to
61
61
  the plugin hooks that take `exam` ({ref}`exam-cache`); for such a plugin the
@@ -107,12 +107,21 @@ design_max_slew: 86.603
107
107
  ```
108
108
 
109
109
  The lines without a prefix are keyword arguments of `pypulseqpp.Opts`, of which
110
- `B0`, the field in T, is required: ppm offsets are resolved at it. The limits
111
- are the `system` the plugin designs under and the checks hold the design to, so
112
- include the scanner's RF and ADC dead times, RF ringdown time and ADC sample
110
+ `B0`, the field in T, is required: ppm offsets are resolved at it. The limits,
111
+ less a design margin, are the `system` the plugin designs under, and the checks
112
+ hold the design to them as sent, so include the scanner's RF and ADC dead times, RF ringdown time and ADC sample
113
113
  divisor; `pypulseqpp.Opts` sets the dead times to zero and the divisor to four
114
114
  when they are left out.
115
115
 
116
+ `max_b1` is the peak B1 the transmit chain allows, in µT, or in the `b1_unit`
117
+ given beside it, as the scanner states it; left out, the pulses are not
118
+ limited. The selective and non-selective excitation and refocusing modules of
119
+ pypulseqpp keep their own duration while the pulse peaks within
120
+ `pypulseqpp.MAX_B1_DERATE` of it, and are otherwise lengthened, flip
121
+ angle and time-bandwidth product held, until it does; the shortest TE and TR a
122
+ plugin reports follow. Spectral, adiabatic, two-dimensional and multiband
123
+ pulses are designed as given.
124
+
116
125
  `max_grad` and `max_slew` are the limits of the gradient coils, to which the
117
126
  checks hold every physical axis. Logical axes played together add on one
118
127
  physical axis, so under an oblique prescription a design held to `max_grad` and
@@ -126,7 +135,11 @@ scanner for the prescription's rotation:
126
135
  | `design_max_slew` | Slew rate each logical axis is designed under, in the `slew_unit` of `max_slew` |
127
136
 
128
137
  A design limit above the scanner's leaves the scanner's, and one left out is the
129
- scanner's. `validate` resolves a request under the same limits as `generate`.
138
+ scanner's. The plugin designs under these limits derated once by
139
+ `pypulseqpp.apply_system_derates`: the gradient amplitude, slew rate and peak
140
+ B1 scaled by `pypulseqpp.MAX_GRAD_DERATE`, `MAX_SLEW_DERATE` and
141
+ `MAX_B1_DERATE`. The checks, the design's identity and its manifest keep the
142
+ limits as the scanner sent them. `validate` resolves a request under the same limits as `generate`.
130
143
  An imported chain is not designed, and is checked against `max_grad` and
131
144
  `max_slew` alone.
132
145
 
@@ -277,7 +290,7 @@ pulserver proxy --store DIR --port N --forward HOST:PORT [--forward-config NAME]
277
290
  | `--forward` | `HOST:PORT` of the MRD server that reconstructs every series, instead of local workers |
278
291
  | `--forward-config` | Config name sent to the `--forward` server; the series' reconstruction plugin when unset |
279
292
  | `--dicom` | Convert each image to DICOM before it is relayed, whatever reconstructed it; for a client that reads DICOM only |
280
- | `--save-data` | Directory each series is kept in as the scanner sends it; kept nowhere when unset |
293
+ | `--save-data` | Directory each series is kept in, enriched; kept nowhere when unset |
281
294
  | `--idle-timeout` | Seconds without a client after which the proxy closes, never while a series is reconstructed. Unlimited when unset |
282
295
  | `--logfile` | File the log is appended to, together with the standard output and error of the proxy and its workers, so whatever a reconstruction plugin logs, prints or warns lands there too; standard error when unset |
283
296
  | `--log-level` | `DEBUG`, `INFO`, `WARNING` or `ERROR`; `INFO` when unset |
@@ -304,10 +317,10 @@ place of a new reconstruction.
304
317
  ### Saved series
305
318
 
306
319
  With `--save-data`, each series is also written to
307
- `<save-data>/mrd_<timestamp>.h5` as the scanner sends it, header first and each
308
- acquisition as it arrives, before it is enriched. `pulserver replay` runs a
309
- plugin on that file and reconstructs it offline as the proxy did
310
- ({ref}`series-replay`). The queue directory holds a series only until it is
320
+ `<save-data>/mrd_<timestamp>.h5` as the proxy reconstructs it: header and
321
+ acquisitions enriched, the header marked `pulserver_enriched`, each acquisition
322
+ as it arrives. `pulserver replay` runs a plugin on that file as it stands and
323
+ gives the image the proxy did ({ref}`series-replay`). The queue directory holds a series only until it is
311
324
  reconstructed.
312
325
 
313
326
  ### Proxy lifetime
@@ -337,9 +350,9 @@ determine when it is reconstructed. The server receives a config file message
337
350
  naming the series' reconstruction plugin, which a reconstruction server runs,
338
351
  or the `--forward-config` name, such as the configuration by which a Gadgetron
339
352
  or FIRE server selects its pipeline. The client's config text is not
340
- forwarded. What the server returns is relayed to the client; a message type the
341
- proxy cannot read ends the relay, and the client receives a `pulserver:` text
342
- naming the type.
353
+ forwarded. What the server returns is relayed to the client once the client's
354
+ stream has ended whole, as from a worker; a message type the proxy cannot read
355
+ ends the relay, and the client receives a `pulserver:` text naming the type.
343
356
 
344
357
  ### Sequence description
345
358