pulserver 0.4.4__tar.gz → 0.4.5__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.
- {pulserver-0.4.4 → pulserver-0.4.5}/.github/workflows/fields.yml +26 -5
- {pulserver-0.4.4 → pulserver-0.4.5}/PKG-INFO +5 -2
- {pulserver-0.4.4 → pulserver-0.4.5}/docker/Dockerfile +6 -10
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/api/proxy.md +2 -1
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/developer-guide/internals/index.md +1 -1
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/developer-guide/internals/ir-cache.md +15 -1
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/developer-guide/internals/protocol-wire.md +7 -3
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/developer-guide/internals/reconstruction-proxy.md +3 -1
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/explanations/raw-data.md +3 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/explanations/reconstruction-session.md +3 -3
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/explanations/scanner-representation.md +5 -3
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/user-guide/reconstruction-client.md +14 -4
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/user-guide/running.md +24 -7
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/user-guide/scanner-sequences.md +2 -2
- {pulserver-0.4.4 → pulserver-0.4.5}/pyproject.toml +4 -1
- {pulserver-0.4.4 → pulserver-0.4.5}/src/c/core/pulseg_error.c +0 -6
- {pulserver-0.4.4 → pulserver-0.4.5}/src/c/include/pulseg/pulseg_collection.h +18 -8
- {pulserver-0.4.4 → pulserver-0.4.5}/src/c/include/pulseg/pulseg_errors.h +0 -1
- {pulserver-0.4.4 → pulserver-0.4.5}/src/c/structure/pulseg_getters.c +55 -33
- {pulserver-0.4.4 → pulserver-0.4.5}/src/cpp/ir/structure.cpp +3 -22
- {pulserver-0.4.4 → pulserver-0.4.5}/src/cpp/module.cpp +7 -4
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/_evaluation.py +19 -6
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/sequences/bssfp2d.py +24 -6
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/sequences/fse3d.py +8 -2
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/sequences/gre2d.py +1 -1
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/sequences/se2d.py +1 -1
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/sequences/zte3d.py +9 -3
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/host/_command.py +1 -1
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/host/_limits.py +40 -2
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/host/_service.py +18 -9
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/proxy/__init__.py +2 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/proxy/__main__.py +36 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/proxy/_enrich.py +37 -4
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/proxy/_held.py +34 -4
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/proxy/_proxy.py +33 -11
- pulserver-0.4.5/src/pulserver/proxy/_receiver.py +97 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/recon/_runtime/mrd2dicom.py +58 -35
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/recon/handlers/nufft.py +16 -3
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/native/read_cache_summary.c +4 -4
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/recon/test_mrd2dicom.py +59 -11
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/recon/test_nufft.py +28 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_console_sequences.py +15 -3
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_enrich.py +23 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_ir.py +38 -1
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_ir_repetition.py +8 -6
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_ir_rf.py +28 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_ir_timing.py +46 -21
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_limits.py +33 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_protocol.py +21 -1
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_proxy.py +102 -4
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_scan_command.py +9 -1
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_virtual.py +21 -5
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_virtual_coils.py +8 -5
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_zoo_evaluation.py +29 -10
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_zoo_wave.py +10 -5
- {pulserver-0.4.4 → pulserver-0.4.5}/.claude/skills/build-and-test/SKILL.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/.claude/skills/write-documentation/SKILL.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/.dockerignore +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/.gitattributes +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/.github/DISCUSSION_TEMPLATE/ideas.yml +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/.github/DISCUSSION_TEMPLATE/q-a.yml +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/.github/ISSUE_TEMPLATE/documentation.yml +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/.github/dependabot.yml +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/.github/workflows/codeql.yml +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/.github/workflows/console.yml +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/.github/workflows/docs.yml +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/.github/workflows/image.yml +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/.github/workflows/koma.yml +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/.github/workflows/style.yml +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/.github/workflows/tags-release.yml +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/.github/workflows/test-ci.yml +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/.github/workflows/wheels.yml +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/.gitignore +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/.pre-commit-config.yaml +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/AGENTS.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/CMakeLists.txt +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/CODE_OF_CONDUCT.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/CONTRIBUTING.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/LICENSE +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/LICENSES/gadgetron-python-MIT.txt +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/LICENSES/python-ismrmrd-server-MIT.txt +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/NEXT.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/README.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/SECURITY.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/SKILLS.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/codecov.yml +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docker/compose.yaml +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docker/entrypoint.sh +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docker/limits/limits.txt +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docker/smoke.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/_static/architecture-dark.svg +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/_static/architecture.svg +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/_static/capabilities.js +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/_static/context-dark.svg +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/_static/context.svg +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/_static/pulseg-dark.svg +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/_static/pulseg.svg +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/_static/pulserver-logo-dark.svg +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/_static/pulserver-logo.svg +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/_static/pulserver-mark-dark.svg +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/_static/pulserver-mark.svg +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/_static/pulserver.css +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/_static/repetition-dark.svg +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/_static/repetition.svg +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/_static/safety-dark.svg +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/_static/safety.svg +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/_static/session-dark.svg +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/_static/session.svg +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/_static/virtual-dark.svg +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/_static/virtual.svg +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/_templates/autosummary/base.rst +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/_templates/autosummary/class.rst +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/_templates/autosummary/enum.rst +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/_templates/autosummary/function.rst +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/api/design.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/api/host.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/api/index.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/api/ir.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/api/mrd.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/api/protocol.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/api/recon.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/api/validate.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/api/virtual.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/api_objects.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/colab.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/conf.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/developer-guide/documentation.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/developer-guide/index.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/developer-guide/installation.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/developer-guide/internals/calibration.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/developer-guide/internals/sar-ratios.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/developer-guide/internals/virtual-scanner.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/developer-guide/releases.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/developer-guide/style.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/developer-guide/terminology.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/developer-guide/workflow.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/examples/course.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/examples/index.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/examples/tours.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/explanations/architecture.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/explanations/index.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/explanations/protocol.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/explanations/reconstruction.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/explanations/safety-checks.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/explanations/virtual-scanner.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/figure_style.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/index.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/misc/contributors.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/misc/index.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/misc/license.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/misc/related.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/user-guide/index.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/user-guide/reconstruction-plugins.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/docs/user-guide/virtual-scanner.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/gallery/01-course/01_protocol_to_image.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/gallery/01-course/02_sequence_plugin.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/gallery/01-course/03_scanner_representation.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/gallery/01-course/04_reconstruction_plugin.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/gallery/01-course/05_recon_plugin.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/gallery/01-course/06_testing_on_the_virtual_scanner.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/gallery/01-course/README.rst +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/gallery/01-course/_gallery_header.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/gallery/02-tours/01_protocol_resolution.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/gallery/02-tours/02_segmentation.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/gallery/02-tours/03_fov_offset_enrichment.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/gallery/02-tours/README.rst +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/gallery/02-tours/_gallery_header.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/gallery/README.rst +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/gallery/_gallery_header.md +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/scripts/build_docs.sh +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/scripts/check_throughput.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/scripts/format_and_lint.sh +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/scripts/make_artwork.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/scripts/publish_docs.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/setup.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/c/CMakeLists.txt +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/c/cache/pulseg_cache.c +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/c/core/pulseg_core.c +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/c/core/pulseg_math.c +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/c/include/pulseg/pulseg.h +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/c/include/pulseg/pulseg_cache.h +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/c/include/pulseg/pulseg_config.h +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/c/include/pulseg/pulseg_io.h +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/c/include/pulseg/pulseg_playout.h +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/c/include/pulseg/pulseg_protocol.h +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/c/include/pulseg/pulseg_types.h +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/c/include/pulseq/pulseq.h +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/c/include/pulseq/pulseq_config.h +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/c/include/pulseq/pulseq_types.h +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/c/io/pulseg_opts.c +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/c/io/pulseg_protocol.c +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/c/playout/pulseg_playout.c +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/c/pulseg_internal.h +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/c/pulseq/pulseq_internal.h +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/c/pulseq/pulseq_shape.c +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/c/structure/pulseg_descriptor.c +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/c/structure/pulseg_repetition.c +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/c/structure/pulseg_waves.c +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/cpp/fourier/bindings.cpp +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/cpp/fourier/bindings.hpp +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/cpp/fourier/parallel.hpp +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/cpp/fourier/timeline.cpp +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/cpp/fourier/timeline.hpp +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/cpp/ir/collection.cpp +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/cpp/ir/dedup.cpp +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/cpp/ir/from_libraries.cpp +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/cpp/ir/from_libraries.hpp +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/cpp/ir/gradient_stretch.cpp +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/cpp/ir/pulseg_convert.h +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/cpp/ir/pulseq_file.cpp +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/cpp/ir/pulseq_file.h +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/cpp/ir/wave_plan.cpp +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/cpp/ir/waves.cpp +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/cpp/native.hpp +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/cpp/playout.cpp +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/cpp/playout.hpp +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/__init__.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_accelerators.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_cli.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_labels.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_logs.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_memory.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_plugins.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/__init__.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/_inversion.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/_pmc.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/_saturation.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/_slab.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/_user.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/recon/epi.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/recon/nufft.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/recon/nufft_train.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/recon/pics.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/recon/pics_train.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/recon/pmc.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/sequences/bssfp3d.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/sequences/epi2d.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/sequences/epi3d.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/sequences/gre3d.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/sequences/gre_multiecho2d.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/sequences/gre_multiecho3d.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/sequences/gre_propeller2d.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/sequences/gre_radial2d.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/sequences/gre_spiral2d.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/sequences/gre_stack_of_blades3d.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/sequences/gre_stack_of_spirals3d.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/sequences/gre_stack_of_stars3d.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/sequences/mprage3d.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/sequences/mprage_stack_of_spirals3d.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/sequences/mprage_stack_of_stars3d.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/sequences/se3d.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/sequences/se_epi_propeller2d.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/sequences/se_propeller2d.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/sequences/se_radial2d.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/sequences/se_spiral2d.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/sequences/se_stack_of_blades3d.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/sequences/se_stack_of_spirals3d.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/_zoo/sequences/se_stack_of_stars3d.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/design/__init__.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/design/_entries.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/design/_options.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/design/_plugin.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/design/_rf.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/host/__init__.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/host/__main__.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/host/_blocks.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/host/_push.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/host/_server.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/host/_store.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/ir/__init__.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/ir/_checks.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/ir/_convert.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/ir/_playout.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/ir/_source.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/ir/_vendor.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/ir/_waves.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/mrd/__init__.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/mrd/_acquisitions.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/mrd/_header.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/mrd/_images.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/mrd/_metadata.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/mrd/_sequence.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/protocol/__init__.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/protocol/_keys.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/protocol/_prescription.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/protocol/_schema.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/protocol/_wire.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/proxy/_designs.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/proxy/_intake.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/proxy/_local.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/proxy/_motion.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/proxy/_queue.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/proxy/_seqdesc.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/proxy/_workers.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/recon/__init__.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/recon/__main__.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/recon/_buffers.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/recon/_calibration.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/recon/_correct.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/recon/_exam_image.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/recon/_figure.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/recon/_loader.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/recon/_replay.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/recon/_runtime/__init__.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/recon/_runtime/application.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/recon/_runtime/concurrency.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/recon/_runtime/connection.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/recon/_runtime/constants.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/recon/_runtime/exam.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/recon/_runtime/offline.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/recon/_runtime/readers.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/recon/_runtime/writers.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/recon/_units.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/recon/gadgets.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/recon/handlers/__init__.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/recon/handlers/epi.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/recon/handlers/nufft_train.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/recon/handlers/pics.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/recon/handlers/pics_train.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/recon/handlers/pmc.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/recon/plugin.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/validate/__init__.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/validate/_command.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/validate/_compare.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/validate/_validate.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/validate/_xml.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/virtual/__init__.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/virtual/_brainweb.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/virtual/_client.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/virtual/_coils.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/virtual/_command.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/virtual/_console.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/virtual/_export.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/virtual/_fourier.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/virtual/_girf.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/virtual/_localizer.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/virtual/_motion.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/virtual/_phantom.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/virtual/_stream.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/virtual/_timeline.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/src/pulserver/virtual/_tissue.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/_analytic.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/_host.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/_seqtext.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/_synthetic.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/_virtual.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/_zoo.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/conftest.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/fixtures/bloch/bssfp.npy +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/fixtures/bloch/epi_2d_main.npy +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/fixtures/bloch/gre_2d_3sl.npy +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/fixtures/bloch/steady_dess_hard_0hz.npy +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/fixtures/bloch/steady_dess_hard_30hz.npy +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/fixtures/bloch/steady_echo_hard_0hz.npy +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/fixtures/bloch/steady_echo_hard_30hz.npy +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/fixtures/bloch/steady_echo_selective_0hz.npy +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/fixtures/bloch/steady_fid_hard_0hz.npy +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/fixtures/sequences/dedup_gre_pair.seq +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/fixtures/sequences/dedup_gre_pair_b.seq +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/fixtures/sequences/epi_2d_main.seq +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/fixtures/sequences/gre_2d_3sl.seq +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/fixtures/sequences/mprage_stack_of_spirals_3d.seq +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/fixtures/sequences/zte_3d.seq +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/koma/Project.toml +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/koma/simulate.jl +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/native/check_initializers.c +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/native/print_wave_samples.c +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/native/read_rf_definitions.c +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/native/read_rf_timing.c +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/native/replay_an_instance.c +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/plugins/crash.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/plugins/gre2d.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/plugins/gre2d_raw.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/plugins/rf_train.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/plugins/stall.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/plugins/strong.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/plugins/tiny.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/plugins/typed.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/recon/test_app.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/recon/test_buffers.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/recon/test_calibration.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/recon/test_coil_compression.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/recon/test_connection.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/recon/test_correct.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/recon/test_epi.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/recon/test_exam_image.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/recon/test_flags.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/recon/test_gadgets.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/recon/test_handlers.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/recon/test_images.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/recon/test_loader.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/recon/test_pics.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/recon/test_pmc.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/recon/test_prewhiten.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/recon/test_readers_writers.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/recon/test_slots.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/recon/test_units.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/recon_plugins/children.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/recon_plugins/crash.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/recon_plugins/device.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/recon_plugins/exam.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/recon_plugins/gre2d.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/recon_plugins/pose.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_console.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_design_push.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_design_server.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_design_service.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_docs.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_docstring_defaults.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_docstrings.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_exam_artifacts.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_exam_calibration.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_exam_sharing.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_host_slots.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_image.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_ir_checks.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_ir_designed.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_ir_extensions.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_ir_gradient_stretch.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_ir_grouping.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_ir_labels.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_ir_playout.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_ir_prescan.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_ir_prescan_tour.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_ir_profile.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_ir_rf_freq.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_ir_segments.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_ir_source.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_ir_steady_excitation.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_ir_vendor.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_ir_waves.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_keys.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_koma.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_logs.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_memory.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_motion.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_mrd_images.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_mrd_sequence.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_plugin_options.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_plugins.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_publish_docs.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_resolution.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_rf_layout.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_seqdesc.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_sequence_plugin.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_smoke.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_validate.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_virtual_brainweb.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_virtual_clock.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_virtual_export.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_virtual_fourier.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_virtual_localizer.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_virtual_sequences.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_wire.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_zoo_defaults.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_zoo_fov_offset.py +0 -0
- {pulserver-0.4.4 → pulserver-0.4.5}/tests/test_zoo_mrd_labels.py +0 -0
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
# BrainWeb's head in the virtual scanner's coils: each coil's transmit and
|
|
2
2
|
# receive maps and the transmit coils' VOPs, solved by mariepy's
|
|
3
|
-
# examples/brainweb.py
|
|
4
|
-
#
|
|
5
|
-
#
|
|
3
|
+
# examples/brainweb.py, published with the normal brain they are solved in as
|
|
4
|
+
# an image that holds only those files, /fields and /brainweb, which
|
|
5
|
+
# docker/Dockerfile copies in by digest, so that no build of pulserver's image
|
|
6
|
+
# reaches BrainWeb's server. mariepy runs here as a program; none of its code
|
|
7
|
+
# enters pulserver or its image.
|
|
6
8
|
name: Fields
|
|
7
9
|
|
|
8
10
|
on:
|
|
@@ -43,8 +45,26 @@ jobs:
|
|
|
43
45
|
python -m pip install torch --index-url https://download.pytorch.org/whl/cpu
|
|
44
46
|
python -m pip install . brainweb-dl scipy
|
|
45
47
|
|
|
48
|
+
# From BrainWeb's server, or, while it does not answer, from the
|
|
49
|
+
# pulserver image that already carries it; either way the same bytes.
|
|
50
|
+
- name: Fetch BrainWeb's normal brain
|
|
51
|
+
env:
|
|
52
|
+
PHANTOM: phantom_1.0mm_normal_fuzzy.nii.gz
|
|
53
|
+
SHA256: cb56eb3e684ddbea48f6146839d18402c742f3b0ffdfb24b3d8ae1e3fc47fc5d
|
|
54
|
+
MIRROR: ghcr.io/pulserver/pulserver@sha256:28a3c682d8ad281e8e3ffd871b03b9477a51c59c373e8a5c41d6f398d085d386
|
|
55
|
+
run: |
|
|
56
|
+
timeout 900 python -c "import brainweb_dl; brainweb_dl.get_mri(0, 'fuzzy', brainweb_dir='brainweb')" || {
|
|
57
|
+
rm -rf brainweb && mkdir brainweb
|
|
58
|
+
cid=$(docker create "$MIRROR")
|
|
59
|
+
docker cp "$cid:/opt/brainweb/$PHANTOM" brainweb/
|
|
60
|
+
docker rm "$cid"
|
|
61
|
+
}
|
|
62
|
+
echo "$SHA256 brainweb/$PHANTOM" | sha256sum -c
|
|
63
|
+
|
|
46
64
|
- name: Solve
|
|
47
|
-
run:
|
|
65
|
+
run: >-
|
|
66
|
+
python examples/brainweb.py --out fields --resolution "$RESOLUTION"
|
|
67
|
+
--brainweb-dir brainweb
|
|
48
68
|
|
|
49
69
|
- name: Record what solved them
|
|
50
70
|
env:
|
|
@@ -65,8 +85,9 @@ jobs:
|
|
|
65
85
|
run: |
|
|
66
86
|
image="ghcr.io/pulserver/brainweb-fields:$(git rev-parse --short HEAD)-${RESOLUTION}mm"
|
|
67
87
|
echo "$TOKEN" | docker login ghcr.io -u "$ACTOR" --password-stdin
|
|
88
|
+
mkdir image && cp -r fields brainweb image/
|
|
68
89
|
printf '%s\n' 'FROM scratch' \
|
|
69
90
|
'LABEL org.opencontainers.image.source=https://github.com/pulserver/pulserver' \
|
|
70
|
-
'COPY . /' | docker build -t "$image" -f -
|
|
91
|
+
'COPY . /' | docker build -t "$image" -f - image
|
|
71
92
|
docker push "$image"
|
|
72
93
|
echo "Published $(docker inspect --format '{{index .RepoDigests 0}}' "$image")" >> "$GITHUB_STEP_SUMMARY"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pulserver
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.5
|
|
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,7 +21,7 @@ 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.
|
|
24
|
+
Requires-Dist: pypulseqpp>=0.0.51
|
|
25
25
|
Requires-Dist: numpy>=2.2.6
|
|
26
26
|
Requires-Dist: ismrmrd>=1.15.0
|
|
27
27
|
Requires-Dist: pydicom>=3.0.2
|
|
@@ -30,7 +30,10 @@ Requires-Dist: blochsim>=0.0.12
|
|
|
30
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
|
+
Provides-Extra: dicom
|
|
34
|
+
Requires-Dist: pynetdicom>=3.0; extra == "dicom"
|
|
33
35
|
Provides-Extra: dev
|
|
36
|
+
Requires-Dist: pynetdicom>=3.0; extra == "dev"
|
|
34
37
|
Requires-Dist: pytest>=9.1.1; extra == "dev"
|
|
35
38
|
Requires-Dist: pytest-cov>=7.1.0; extra == "dev"
|
|
36
39
|
Requires-Dist: pytest-xdist>=3; extra == "dev"
|
|
@@ -38,17 +38,13 @@ RUN pip install --no-cache-dir "$(echo /wheels/pulserver-*.whl)" \
|
|
|
38
38
|
# installed from PyPI, where its source is.
|
|
39
39
|
RUN pip install --no-cache-dir "bartorch[pyhysco]"
|
|
40
40
|
|
|
41
|
-
# BrainWeb's normal brain,
|
|
42
|
-
#
|
|
41
|
+
# BrainWeb's normal brain, and the coils' field maps and VOPs that the Fields
|
|
42
|
+
# workflow solves in it with mariepy, which that workflow publishes as an image
|
|
43
|
+
# of those files alone, so that neither a build nor an exam reaches BrainWeb's
|
|
44
|
+
# server; brainweb-dl reads the brain from BRAINWEB_DIR.
|
|
43
45
|
ENV BRAINWEB_DIR=/opt/brainweb
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
rm -rf "$BRAINWEB_DIR"; [ "$attempt" = 3 ] && exit 1; sleep 30; \
|
|
47
|
-
done
|
|
48
|
-
|
|
49
|
-
# The coils' field maps and VOPs, which the Fields workflow solves in the same
|
|
50
|
-
# brain with mariepy and publishes as an image of those files alone.
|
|
51
|
-
COPY --from=ghcr.io/pulserver/brainweb-fields@sha256:c102b4f2563e1a1a19ca25d9cd3b9b9d7505555041b4795310aee4725a659ddb / /console/fields/
|
|
46
|
+
COPY --from=ghcr.io/pulserver/brainweb-fields@sha256:b6ca42ee0d21e16fccb77fee165f15fa7b77dc2f6073ade0ff7000c902e3acb6 /brainweb/ /opt/brainweb/
|
|
47
|
+
COPY --from=ghcr.io/pulserver/brainweb-fields@sha256:b6ca42ee0d21e16fccb77fee165f15fa7b77dc2f6073ade0ff7000c902e3acb6 /fields/ /console/fields/
|
|
52
48
|
|
|
53
49
|
# The limits the console's sequences design under.
|
|
54
50
|
COPY docker/limits/limits.txt /console/limits.txt
|
|
@@ -11,7 +11,7 @@ and runs it on a reconstruction worker.
|
|
|
11
11
|
The proxy listens on a TCP port and is started with
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
-
pulserver proxy --store DIR --port N --plugins DIR [--intake-port N] [--slots N] [--spares 1] [--save-data DIR] [--idle-timeout S]
|
|
14
|
+
pulserver proxy --store DIR --port N --plugins DIR [--intake-port N] [--slots N] [--spares 1] [--dicom-receiver HOST:PORT --dicom-receiver-title AE] [--save-data DIR] [--idle-timeout S]
|
|
15
15
|
pulserver proxy --store DIR --port N --forward HOST:PORT [--forward-config NAME] [--dicom]
|
|
16
16
|
```
|
|
17
17
|
|
|
@@ -35,6 +35,7 @@ and fields of a series in {doc}`../user-guide/reconstruction-client`.
|
|
|
35
35
|
| --- | --- |
|
|
36
36
|
| {obj}`~pulserver.proxy.ReconProxy` | TCP MRD server enriching each series and routing it to a reconstruction worker or server. |
|
|
37
37
|
| {obj}`~pulserver.proxy.ReconServer` | TCP MRD server reconstructing each series with the plugin its config names. |
|
|
38
|
+
| {obj}`~pulserver.proxy.DicomReceiver` | DICOM storage service the images of a series whose client has gone are stored to. |
|
|
38
39
|
| {obj}`~pulserver.proxy.LocalReconstruction` | Each series checked, enriched and reconstructed in the calling process, as the proxy's workers do, for a host that starts no processes. |
|
|
39
40
|
|
|
40
41
|
## Designs
|
|
@@ -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 gradient stretches, the cache file and the C89 library |
|
|
10
|
+
| {doc}`ir-cache` | Conversion passes, waves, playout stages, the gradient stretches, the RF averaging span, 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 |
|
|
@@ -48,7 +48,7 @@ and two designs ({doc}`../../explanations/architecture`).
|
|
|
48
48
|
| Pass | Result |
|
|
49
49
|
| --- | --- |
|
|
50
50
|
| Event deduplication | A library of distinct RF, gradient and ADC definitions, and a per-block instance table recording the definition each block plays and its amplitude |
|
|
51
|
-
| Repetition | The repetition of each subsequence and its repetition time (TR): the period pypulseqpp's `Sequence.repetition` finds, from the first block; a subsequence that does not repeat is one repetition,
|
|
51
|
+
| Repetition | The repetition of each subsequence and its repetition time (TR): the period pypulseqpp's `Sequence.repetition` finds, from the first block; a subsequence that does not repeat is one repetition, however long |
|
|
52
52
|
| Segmentation | The repetition divided into virtual segments at block boundaries the {class}`~pulserver.ir.Grouping` admits |
|
|
53
53
|
| Execution stream | The segment instances of the whole scan, in play order |
|
|
54
54
|
| Label table | The Pulseq labels in force at every readout, three of which fill the ADC label columns |
|
|
@@ -292,6 +292,20 @@ axes and linear in between; the prescription's rotation takes them to the
|
|
|
292
292
|
physical axes, and a model that needs them on a raster samples them at the
|
|
293
293
|
centres of its intervals (`pulseg_sample_corner_points`).
|
|
294
294
|
|
|
295
|
+
## RF averaging span
|
|
296
|
+
|
|
297
|
+
A scanner holds SAR and its RF amplifier to averages over windows, such as
|
|
298
|
+
10 s and 6 min. `pulseg_get_rf_window` gives the span of a subsequence a
|
|
299
|
+
window is costed over, and the plays of each pulse of the repetition in it,
|
|
300
|
+
each play at its block's start and weighed by the energy the caller gives its
|
|
301
|
+
pulse. The span is costed over its own duration.
|
|
302
|
+
|
|
303
|
+
| Subsequence | Span |
|
|
304
|
+
|---|---|
|
|
305
|
+
| Its hyper-repetition repeats and is shorter than the window | One hyper-repetition from the start, which plays at the subsequence's mean power; a window-long span would add up to one repetition's energy at its edges. Weighed by `pulseg_get_rf_array`, which takes each pulse at the worst repetition instance, the repetition of largest $\sum A^2 P$, every repetition in it plays as that instance |
|
|
306
|
+
| No longer than the window | The whole subsequence |
|
|
307
|
+
| Otherwise | Of the window-long spans starting at a play or ending at the subsequence's end, the one of most energy, the earliest on a tie; plays are costed by count, so unlike a gradient stretch it is not widened to whole segment instances |
|
|
308
|
+
|
|
295
309
|
## Cache file
|
|
296
310
|
|
|
297
311
|
The cache has the name of the first sequence file with its extension replaced,
|
|
@@ -45,7 +45,11 @@ sequence the evaluation builds, in the order of first play. The listing carries
|
|
|
45
45
|
the definitions of the evaluation at the default protocol, and a layout names
|
|
46
46
|
the pulses of the listing only where the protocol does not change which pulses
|
|
47
47
|
are played first: the length of a train, a flip angle schedule and the matrix do
|
|
48
|
-
not, and a protocol that adds a preparation pulse does.
|
|
48
|
+
not, and a protocol that adds a preparation pulse does. Explicit saturation
|
|
49
|
+
bands are the exception a console needs, since it places them without listing
|
|
50
|
+
again: the listing's evaluation places every band the plugin offers, and the
|
|
51
|
+
shipped plugins number the band pulse after the others, so a band placed or
|
|
52
|
+
removed changes no other number.
|
|
49
53
|
|
|
50
54
|
The layout is an estimate for the prescription. An evaluation that states none
|
|
51
55
|
states no estimate and is valid, and what the scanner checks before the scan is
|
|
@@ -115,8 +119,8 @@ where the evaluation is invalid or states no layout. They are lists of numbers:
|
|
|
115
119
|
each number is ASCII decimal with nine significant digits, the numbers of a list
|
|
116
120
|
are separated by single spaces, and each list is one line, so that a reader
|
|
117
121
|
takes tokens. `[RfDefinitions]` follows the listing of a `list` call asked with
|
|
118
|
-
`rf_definitions`, which evaluates the plugin at its default protocol
|
|
119
|
-
scanner limits. Each definition is a `definition` line, then the sample times,
|
|
122
|
+
`rf_definitions`, which evaluates the plugin at its default protocol, with
|
|
123
|
+
every explicit saturation band it offers placed, under the scanner limits. Each definition is a `definition` line, then the sample times,
|
|
120
124
|
then the real and the imaginary parts of each channel:
|
|
121
125
|
|
|
122
126
|
```text
|
|
@@ -252,7 +252,9 @@ is applied to the stream as follows.
|
|
|
252
252
|
on the flat top of its readout gradient alone. In a stack of slices, its
|
|
253
253
|
position, the field-of-view centre the client sends, is moved along
|
|
254
254
|
`slice_dir` by the `SlicePositions` entry its `SLC` indexes, to the centre of
|
|
255
|
-
its slice
|
|
255
|
+
its slice, and by half a voxel along each axis of even matrix size, its
|
|
256
|
+
samples given the phase of the same shift, so that the reconstruction grid
|
|
257
|
+
is centred on the field of view (`SequenceTable.grid_offset_m`). When the client numbers its
|
|
256
258
|
acquisitions, each `scan_counter` must follow the previous one by one; a gap
|
|
257
259
|
or a repeat stops the series before it is reconstructed, since every later
|
|
258
260
|
row would be shifted.
|
|
@@ -44,6 +44,9 @@ before and after.
|
|
|
44
44
|
- **Applies the field-of-view phase the scanner's offsets cannot, and any later position change in the header.**
|
|
45
45
|
|
|
46
46
|
Code: {mod}`pulserver.proxy`. Tests: *a curving readout carries the phase its receiver cannot apply*; *a steady readout needs no curve*; *a stated position away from the converted shift adds its whole phase* (`test_enrich.py`).
|
|
47
|
+
- **Centres the reconstruction grid on the field of view, voxel centres symmetric about the prescribed centre.**
|
|
48
|
+
|
|
49
|
+
Code: `SequenceTable.grid_offset_m`. Tests: *the reconstruction grid is centred half a voxel from an fft one* (`test_enrich.py`); *a point off the centre reconstructs where it was acquired* (`test_proxy.py`).
|
|
47
50
|
- **Writes TR, TE, TI and flip angles into the header, measuring the ones the sequence does not define.**
|
|
48
51
|
|
|
49
52
|
Code: {mod}`pulserver.mrd`. Tests: *te and tr a sequence does not define are the ones pypulseqpp measures*; *the header lists every flip angle the sequence plays* (`test_mrd_sequence.py`, `test_enrich.py`).
|
|
@@ -56,10 +56,10 @@ on the other end refuses a series it cannot serve, enriches it from its design
|
|
|
56
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`).
|
|
57
57
|
- **Keeps each series enriched, for an offline rerun that gives the same image.**
|
|
58
58
|
|
|
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`).
|
|
60
|
-
- **Holds images for a client that dropped, and closes on its own when idle.**
|
|
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*; *a kept series takes its name only once its stream has ended* (`test_proxy.py`).
|
|
60
|
+
- **Holds images for a client that dropped, or stores them to a DICOM receiver, and closes on its own when idle.**
|
|
61
61
|
|
|
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`).
|
|
62
|
+
Code: `--idle-timeout`, `--dicom-receiver`. Tests: *images whose client has gone reach it when it returns*; *the images of a series whose client has gone reach the dicom receiver*; *a series the dicom receiver does not take is held for its client*; *the idle timeout counts from the last client leaving* (`test_proxy.py`).
|
|
63
63
|
|
|
64
64
|
:::
|
|
65
65
|
|
|
@@ -25,9 +25,9 @@ its segments.
|
|
|
25
25
|
- **Takes the repetition pypulseqpp reports, and segments within it.**
|
|
26
26
|
|
|
27
27
|
Code: `src/cpp/ir/structure.cpp`. Tests: *the ir segments the repetition pypulseqpp finds*; *a hyper tr declared as pypulseqpp writes it is the repeating unit* (`test_ir_repetition.py`).
|
|
28
|
-
- **Treats a sequence that does not repeat as one repetition,
|
|
28
|
+
- **Treats a sequence that does not repeat as one repetition, however long it plays.**
|
|
29
29
|
|
|
30
|
-
Code: `
|
|
30
|
+
Code: `src/cpp/ir/structure.cpp`. Tests: *a sequence that does not repeat is one repetition*; *a sequence that does not repeat is one repetition however long it plays* (`test_ir_repetition.py`); *a repetition past a 32 bit count of microseconds reads the same in the scanner reader* (`test_ir.py`).
|
|
31
31
|
- **Cuts virtual segments only where every gradient is near zero, under a tunable grouping.**
|
|
32
32
|
|
|
33
33
|
Code: {class}`~pulserver.ir.Grouping`. Tests: *the default grouping is what a conversion does unasked*; *a grouping moves the boundaries and not the gradient* (`test_ir_grouping.py`); *a gradient its file ends live may not end the repetition* (`test_ir.py`).
|
|
@@ -98,7 +98,9 @@ at the first block and is the first of these that applies:
|
|
|
98
98
|
3. The shortest period dividing the sequence over which blocks match in
|
|
99
99
|
duration and in the channels they play, so that shots with their own
|
|
100
100
|
pulses or gradient shapes still repeat.
|
|
101
|
-
4. Otherwise the whole file is one repetition,
|
|
101
|
+
4. Otherwise the whole file is one repetition, however long. Nothing holds a
|
|
102
|
+
repetition's samples: the timing and RF costing walk its blocks and plays,
|
|
103
|
+
and gradient heating is costed over stretches of at most `PULSEG_STRETCH_US`.
|
|
102
104
|
|
|
103
105
|
A slice played with its own preparation and dummy shots is therefore one
|
|
104
106
|
repetition, and a block played once makes the whole file one. The segment IDs
|
|
@@ -86,8 +86,8 @@ of the image it is written into; `{{` and `}}` are literal braces:
|
|
|
86
86
|
| Name | Value |
|
|
87
87
|
| --- | --- |
|
|
88
88
|
| `slice_location` | The image centre along the plane normal, in mm: the `SliceLocation` written by default |
|
|
89
|
-
| `location` | The image centre
|
|
90
|
-
| `location_letter` | The side `location` lies on: `R` or `L`, `A` or `P`, `S` or `I
|
|
89
|
+
| `location` | The image centre's coordinate on the patient axis the normal lies closest to, in mm, positive towards right, anterior or superior; an oblique plane is located on that axis too |
|
|
90
|
+
| `location_letter` | The side `location` lies on: `R` or `L`, `A` or `P`, `S` or `I` |
|
|
91
91
|
| `instance_number`, `series_number` | The image's `InstanceNumber` and `SeriesNumber` |
|
|
92
92
|
|
|
93
93
|
An attribute that resolves to no tag, for want of the dictionary, is logged and
|
|
@@ -103,15 +103,25 @@ noise scans and navigators included, and no other.
|
|
|
103
103
|
| Field | Client | Proxy |
|
|
104
104
|
| --- | --- | --- |
|
|
105
105
|
| `number_of_samples` | The sample count of the readout's ADC event | Checked |
|
|
106
|
-
| `active_channels`, data | The samples, demodulated by each ADC's frequency and phase offsets | Multiplied by the phase a field-of-view offset adds to a readout under a moving gradient, and by any phase modulation the sequence file stores |
|
|
106
|
+
| `active_channels`, data | The samples, demodulated by each ADC's frequency and phase offsets | Multiplied by the phase a field-of-view offset adds to a readout under a moving gradient, by the phase that centres the reconstruction grid (below), and by any phase modulation the sequence file stores |
|
|
107
107
|
| `scan_counter` | 0 on every acquisition, or increasing by one from any start | Checked |
|
|
108
108
|
| `flags` | None, or `LAST_IN_MEASUREMENT` on the last acquisition | Replaced |
|
|
109
109
|
| `idx`, `sample_time_us`, `encoding_space_ref` | Any value | Replaced |
|
|
110
110
|
| `center_sample` | Any value | Replaced, except on a readout whose k-space location does not change |
|
|
111
111
|
| `trajectory_dimensions`, `traj` | Any value | Replaced on a readout whose k-space location changes, in 1/m along the sequence's gradient axes |
|
|
112
|
-
| `position` | The prescribed field-of-view centre, in mm from isocentre | Moved along `slice_dir` to the centre of the readout's slice, for a stack of 2D slices whose sequence defines `SlicePositions
|
|
112
|
+
| `position` | The prescribed field-of-view centre, in mm from isocentre | Moved along `slice_dir` to the centre of the readout's slice, for a stack of 2D slices whose sequence defines `SlicePositions`, and by half a voxel along each axis of even matrix size (below); an image takes it from its reference acquisition |
|
|
113
113
|
| `measurement_uid`, `read_dir`, `phase_dir`, `slice_dir`, `patient_table_position`, `acquisition_time_stamp`, `physiology_time_stamp`, `user_int`, `user_float` | The scanner's values, as MRD defines them | Passed on unchanged; an image takes them from its reference acquisition |
|
|
114
114
|
|
|
115
|
+
The reconstruction grid is centred on the field of view: the voxel centres of
|
|
116
|
+
an axis of `n` voxels lie symmetrically about the prescribed centre, at
|
|
117
|
+
`(i - (n - 1) / 2)` voxels from it. An FFT puts the centre on voxel `n // 2`
|
|
118
|
+
instead, half a voxel off along an axis of even `n`, so each acquisition's
|
|
119
|
+
`position` is moved by `FOV / (2 n)` along each such axis of its encoding
|
|
120
|
+
space's matrix, and its samples are given the phase of the same shift of the
|
|
121
|
+
field of view. Voxel `n // 2` of the reconstruction, which MRD's `position`
|
|
122
|
+
locates, then lies half a voxel past the prescribed centre, and the content
|
|
123
|
+
moves with it.
|
|
124
|
+
|
|
115
125
|
A series is refused, and its reconstruction stopped, when an acquisition has a
|
|
116
126
|
sample count other than its readout's, when the scan counters skip or repeat
|
|
117
127
|
one, when an acquisition before the last is flagged `LAST_IN_MEASUREMENT`,
|
|
@@ -50,8 +50,9 @@ in {doc}`../explanations/protocol`.
|
|
|
50
50
|
|
|
51
51
|
The RF blocks are sent only when asked for, and only where the plugin's
|
|
52
52
|
evaluation states an RF layout ({ref}`stating-the-rf-layout`).
|
|
53
|
-
`--rf-definitions` evaluates the plugin at its default protocol
|
|
54
|
-
|
|
53
|
+
`--rf-definitions` evaluates the plugin at its default protocol, with every
|
|
54
|
+
explicit saturation band it offers placed, under `--limits`, which it then
|
|
55
|
+
requires. `--rf-layout` follows a valid reply with the
|
|
55
56
|
RF layout of the evaluated request, its amplitudes relative to the peaks the
|
|
56
57
|
listing states. Without `--rf-definitions`, `list` depends on the plugin file,
|
|
57
58
|
its options and the installed packages only, so its reply can be written once
|
|
@@ -133,9 +134,16 @@ scanner for the prescription's rotation:
|
|
|
133
134
|
| --- | --- |
|
|
134
135
|
| `design_max_grad` | Gradient amplitude each logical axis is designed under, in the `grad_unit` of `max_grad` |
|
|
135
136
|
| `design_max_slew` | Slew rate each logical axis is designed under, in the `slew_unit` of `max_slew` |
|
|
137
|
+
| `design_rf_dead_time` | Least delay of an RF pulse in its block, in s |
|
|
138
|
+
| `design_rf_ringdown_time` | Least time from the end of an RF pulse to the end of its block, in s |
|
|
139
|
+
| `design_adc_dead_time` | Least delay of a readout in its block, and least time after it, in s |
|
|
136
140
|
|
|
137
141
|
A design limit above the scanner's leaves the scanner's, and one left out is the
|
|
138
|
-
scanner's
|
|
142
|
+
scanner's; a design dead time below the scanner's leaves the scanner's. The
|
|
143
|
+
design dead times are the room a playout needs around an RF pulse or a readout
|
|
144
|
+
in some layouts and not in others, such as a readout that starts right after
|
|
145
|
+
its excitation: designs make it everywhere, and the checks, which hold a file
|
|
146
|
+
to the scanner's own dead times, do not ask it of an imported chain. The plugin designs under these limits derated once by
|
|
139
147
|
`pypulseqpp.apply_system_derates`: the gradient amplitude, slew rate and peak
|
|
140
148
|
B1 scaled by `pypulseqpp.MAX_GRAD_DERATE`, `MAX_SLEW_DERATE` and
|
|
141
149
|
`MAX_B1_DERATE`. The checks, the design's identity and its manifest keep the
|
|
@@ -270,8 +278,8 @@ scan beside the rest of that scan's log.
|
|
|
270
278
|
## Reconstruction proxy
|
|
271
279
|
|
|
272
280
|
```bash
|
|
273
|
-
pulserver proxy --store DIR --port N --plugins DIR [--host ADDR] [--intake-port N] [--queue DIR] [--exams DIR] [--slots N] [--gpu-slots 1] [--spares 1] [--recon-timeout S] [--dicom] [--save-data DIR] [--idle-timeout S] [--logfile FILE] [--log-level LEVEL]
|
|
274
|
-
pulserver proxy --store DIR --port N --forward HOST:PORT [--forward-config NAME] [--host ADDR] [--intake-port N] [--recon-timeout S] [--dicom] [--save-data DIR] [--idle-timeout S] [--logfile FILE] [--log-level LEVEL]
|
|
281
|
+
pulserver proxy --store DIR --port N --plugins DIR [--host ADDR] [--intake-port N] [--queue DIR] [--exams DIR] [--slots N] [--gpu-slots 1] [--spares 1] [--recon-timeout S] [--dicom] [--dicom-receiver HOST:PORT --dicom-receiver-title AE [--dicom-title AE]] [--save-data DIR] [--idle-timeout S] [--logfile FILE] [--log-level LEVEL]
|
|
282
|
+
pulserver proxy --store DIR --port N --forward HOST:PORT [--forward-config NAME] [--host ADDR] [--intake-port N] [--recon-timeout S] [--dicom] [--dicom-receiver HOST:PORT --dicom-receiver-title AE [--dicom-title AE]] [--save-data DIR] [--idle-timeout S] [--logfile FILE] [--log-level LEVEL]
|
|
275
283
|
```
|
|
276
284
|
|
|
277
285
|
| Option | Meaning |
|
|
@@ -290,6 +298,9 @@ pulserver proxy --store DIR --port N --forward HOST:PORT [--forward-config NAME]
|
|
|
290
298
|
| `--forward` | `HOST:PORT` of the MRD server that reconstructs every series, instead of local workers |
|
|
291
299
|
| `--forward-config` | Config name sent to the `--forward` server; the series' reconstruction plugin when unset |
|
|
292
300
|
| `--dicom` | Convert each image to DICOM before it is relayed, whatever reconstructed it; for a client that reads DICOM only |
|
|
301
|
+
| `--dicom-receiver` | `HOST:PORT` of a DICOM storage service the images of a series whose client has gone are stored to by C-STORE; held for the client's return when unset. Needs `pynetdicom` (`pulserver[dicom]`) |
|
|
302
|
+
| `--dicom-receiver-title` | Application entity title of the `--dicom-receiver`; required with it |
|
|
303
|
+
| `--dicom-title` | Application entity title the proxy calls the `--dicom-receiver` as; `PULSERVER` when unset |
|
|
293
304
|
| `--save-data` | Directory each series is kept in, enriched; kept nowhere when unset |
|
|
294
305
|
| `--idle-timeout` | Seconds without a client after which the proxy closes, never while a series is reconstructed. Unlimited when unset |
|
|
295
306
|
| `--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 |
|
|
@@ -312,14 +323,20 @@ A series that finds every slot busy is written to the queue directory as it
|
|
|
312
323
|
arrives and reconstructed once a slot frees; the client stays connected
|
|
313
324
|
meanwhile. What goes back to a client whose connection has dropped is kept for
|
|
314
325
|
a day: a client that opens a series with the same `measurementID` is sent it in
|
|
315
|
-
place of a new reconstruction.
|
|
326
|
+
place of a new reconstruction. With `--dicom-receiver`, the series' DICOM
|
|
327
|
+
images are stored to the receiver instead once its reconstruction ends, all of
|
|
328
|
+
them, since which ones the client read before it went cannot be told; the
|
|
329
|
+
output is kept only if the receiver did not store every one. A scanner client
|
|
330
|
+
whose process may be ended before a slow reconstruction finishes names its
|
|
331
|
+
image database here.
|
|
316
332
|
|
|
317
333
|
### Saved series
|
|
318
334
|
|
|
319
335
|
With `--save-data`, each series is also written to
|
|
320
336
|
`<save-data>/mrd_<timestamp>.h5` as the proxy reconstructs it: header and
|
|
321
337
|
acquisitions enriched, the header marked `pulserver_enriched`, each acquisition
|
|
322
|
-
as it arrives.
|
|
338
|
+
as it arrives. Until the stream ends the file is `mrd_<timestamp>.h5.part`, so
|
|
339
|
+
whatever collects the directory can tell a series still arriving. `pulserver replay` runs a plugin on that file as it stands and
|
|
323
340
|
gives the image the proxy did ({ref}`series-replay`). The queue directory holds a series only until it is
|
|
324
341
|
reconstructed.
|
|
325
342
|
|
|
@@ -433,7 +433,7 @@ saturation bands are the console's own controls:
|
|
|
433
433
|
The saturation bands of `gre2d` and `se2d` are placed graphically, as a
|
|
434
434
|
scanner's console places an explicit band, and each is played before every
|
|
435
435
|
excitation while it is placed; a plugin offers as many bands as its module
|
|
436
|
-
constant `BANDS`,
|
|
436
|
+
constant `BANDS`, 6, and refuses a mask placing more.
|
|
437
437
|
`exsat<n>_normal_x`, `_y` and `_z`, `exsat<n>_loc` and `exsat<n>_thickness`
|
|
438
438
|
give each band's normal along the physical axes, the distance of its centre
|
|
439
439
|
from the isocentre along that normal, and its thickness, in mm. The
|
|
@@ -487,7 +487,7 @@ same user entry in every plugin:
|
|
|
487
487
|
| `gre3d`, `gre_multiecho3d`, `mprage3d`, `fse3d` | `wave` | `user37` | Wave-CAIPI; the calibration region is acquired first without the wave, and `pics` and `pmc` reconstruct the wave-encoded volume | `user10` and `user11`: wave amplitude and cycles |
|
|
488
488
|
| `gre3d`, `se3d`, `gre_multiecho3d` | `elliptical` | `user40` | Only the phase encodes inside the ky-kz ellipse; on by default | None |
|
|
489
489
|
| `gre_multiecho2d`, `gre_multiecho3d` | `flyback` | `user41` | Monopolar echoes, on by default; off reads even echoes reversed | None |
|
|
490
|
-
| `zte3d` | `scheme` | `user43` | Spokes ordered `"spiral"` or `"
|
|
490
|
+
| `zte3d` | `scheme` | `user43` | Spokes ordered `"spiral"`, at a constant step across many rings; `"meridian"`; or `"quiet"`, the default: the spiral's directions in steps about a ring gap long, every other shell played backwards | None |
|
|
491
491
|
| `bssfp2d` | `retrospective` | `user44` | ECG gating: off, prospective, each heartbeat triggered and acquired once per cardiac phase; on, retrospective, each segment cycled over a heartbeat and binned into cardiac phases by the reconstruction | None |
|
|
492
492
|
| `gre_spiral2d`, `se_spiral2d`, `gre_stack_of_spirals3d`, `se_stack_of_spirals3d`, `mprage_stack_of_spirals3d` | `variable_density` | `user42` | Variable-density spirals | `user12`: periphery undersampling |
|
|
493
493
|
|
|
@@ -24,7 +24,7 @@ classifiers = [
|
|
|
24
24
|
]
|
|
25
25
|
|
|
26
26
|
dependencies = [
|
|
27
|
-
"pypulseqpp>=0.0.
|
|
27
|
+
"pypulseqpp>=0.0.51",
|
|
28
28
|
"numpy>=2.2.6",
|
|
29
29
|
"ismrmrd>=1.15.0",
|
|
30
30
|
"pydicom>=3.0.2",
|
|
@@ -37,7 +37,10 @@ dependencies = [
|
|
|
37
37
|
]
|
|
38
38
|
|
|
39
39
|
[project.optional-dependencies]
|
|
40
|
+
# The proxy's --dicom-receiver: images stored by C-STORE.
|
|
41
|
+
dicom = ["pynetdicom>=3.0"]
|
|
40
42
|
dev = [
|
|
43
|
+
"pynetdicom>=3.0",
|
|
41
44
|
"pytest>=9.1.1",
|
|
42
45
|
"pytest-cov>=7.1.0",
|
|
43
46
|
"pytest-xdist>=3",
|
|
@@ -81,8 +81,6 @@ const char *pulseg_get_error_message(int code)
|
|
|
81
81
|
return "A segment is played with too many distinct pulse patterns";
|
|
82
82
|
case PULSEG_ERR_TR_NO_BLOCKS:
|
|
83
83
|
return "Sequence contains no blocks";
|
|
84
|
-
case PULSEG_ERR_TR_NO_PERIODIC_PATTERN:
|
|
85
|
-
return "No periodic TR pattern found";
|
|
86
84
|
case PULSEG_ERR_SEG_NONZERO_START_GRAD:
|
|
87
85
|
return "TR does not start with zero gradient amplitude";
|
|
88
86
|
case PULSEG_ERR_SEG_NONZERO_END_GRAD:
|
|
@@ -154,10 +152,6 @@ const char *pulseg_get_error_hint(int code)
|
|
|
154
152
|
case PULSEG_ERR_SIGNATURE_MISSING:
|
|
155
153
|
return "The .seq file does not contain a [SIGNATURE] section. "
|
|
156
154
|
"Re-export the sequence to include a signature.";
|
|
157
|
-
case PULSEG_ERR_TR_NO_PERIODIC_PATTERN:
|
|
158
|
-
return "This often occurs when phase-encoding gradients are created inside "
|
|
159
|
-
"the sequence loop with varying amplitudes. Instead, create gradient "
|
|
160
|
-
"events ONCE outside the loop and use 'scale' parameter to vary amplitude.";
|
|
161
155
|
case PULSEG_ERR_SEG_NONZERO_START_GRAD:
|
|
162
156
|
case PULSEG_ERR_SEG_NONZERO_END_GRAD:
|
|
163
157
|
return "Each segment must begin and end with gradient amplitudes that can "
|
|
@@ -289,33 +289,43 @@ extern "C"
|
|
|
289
289
|
int subseq_idx);
|
|
290
290
|
|
|
291
291
|
/**
|
|
292
|
-
* @brief The span of a subsequence's timeline
|
|
293
|
-
*
|
|
292
|
+
* @brief The span of a subsequence's timeline over which its RF plays are
|
|
293
|
+
* averaged against a window, as plays per pulse of the repetition.
|
|
294
294
|
*
|
|
295
295
|
* Each play is placed at the start of its block, every block timed at its
|
|
296
296
|
* own duration, and weighs @p weights[k], k being its pulse in the
|
|
297
|
-
* repetition as pulseg_get_rf_array() orders them.
|
|
298
|
-
*
|
|
299
|
-
*
|
|
300
|
-
*
|
|
297
|
+
* repetition as pulseg_get_rf_array() orders them. Where the
|
|
298
|
+
* hyper-repetition repeats and is shorter than @p window_us, it is the
|
|
299
|
+
* span: every window averages what it does, and weighed by
|
|
300
|
+
* pulseg_get_rf_array(), every repetition plays at the worst repetition
|
|
301
|
+
* instance's amplitudes. Otherwise a subsequence no
|
|
302
|
+
* longer than the window is the span. Otherwise, of the half-open spans of
|
|
303
|
+
* @p window_us starting at a play, or ending at the subsequence's end, the
|
|
304
|
+
* one of largest total weight is taken, the earliest on a tie: plays are
|
|
305
|
+
* costed by count, so the span needs no whole segment instances. Two
|
|
306
|
+
* passes over the execution stream, no allocation.
|
|
301
307
|
*
|
|
302
308
|
* @param[in] coll Loaded collection, with its execution stream.
|
|
303
309
|
* @param[in] subseq_idx Subsequence index.
|
|
304
|
-
* @param[in]
|
|
310
|
+
* @param[in] timing Its pulseg_get_tr_timing().
|
|
311
|
+
* @param[in] window_us Averaging window, us; > 0.
|
|
305
312
|
* @param[in] weights Energy of one play of each pulse of the repetition.
|
|
306
313
|
* @param[in] num_weights Pulses in the repetition.
|
|
307
314
|
* @param[out] counts num_weights entries: plays of each pulse in the span.
|
|
308
315
|
* @param[out] start_us Where the span starts; may be NULL.
|
|
316
|
+
* @param[out] span_us Its duration, the one to average over; may be NULL.
|
|
309
317
|
* @return Plays in the span (0 without RF), or a negative error code.
|
|
310
318
|
*/
|
|
311
319
|
int pulseg_get_rf_window(
|
|
312
320
|
const pulseg_collection *coll,
|
|
313
321
|
int subseq_idx,
|
|
322
|
+
const pulseg_tr_timing *timing,
|
|
314
323
|
double window_us,
|
|
315
324
|
const double *weights,
|
|
316
325
|
int num_weights,
|
|
317
326
|
int *counts,
|
|
318
|
-
double *start_us
|
|
327
|
+
double *start_us,
|
|
328
|
+
double *span_us);
|
|
319
329
|
|
|
320
330
|
/**
|
|
321
331
|
* @brief Return decompressed RF magnitude waveform (multi-channel).
|