brkraw 0.5.2__tar.gz → 0.5.3__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 (193) hide show
  1. {brkraw-0.5.2 → brkraw-0.5.3}/.github/workflows/release_on_merge.yml +2 -3
  2. {brkraw-0.5.2 → brkraw-0.5.3}/CITATION.cff +1 -1
  3. {brkraw-0.5.2 → brkraw-0.5.3}/PKG-INFO +7 -8
  4. {brkraw-0.5.2 → brkraw-0.5.3}/README.md +5 -7
  5. brkraw-0.5.3/RELEASE_NOTES.md +13 -0
  6. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/__init__.py +1 -1
  7. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/apps/loader/core.py +3 -11
  8. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/apps/loader/helper.py +171 -64
  9. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/apps/loader/types.py +24 -47
  10. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/cli/commands/convert.py +5 -24
  11. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/cli/commands/hook.py +0 -2
  12. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/cli/commands/session.py +1 -11
  13. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/resolver/nifti.py +4 -12
  14. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/schema/niftiheader.yaml +0 -2
  15. {brkraw-0.5.2 → brkraw-0.5.3}/docs/api/convert.md +1 -5
  16. {brkraw-0.5.2 → brkraw-0.5.3}/docs/api/data-access.md +2 -2
  17. {brkraw-0.5.2 → brkraw-0.5.3}/docs/api/overview.md +0 -2
  18. {brkraw-0.5.2 → brkraw-0.5.3}/docs/cli/session.md +2 -2
  19. {brkraw-0.5.2 → brkraw-0.5.3}/docs/dev/contributors.md +1 -1
  20. {brkraw-0.5.2 → brkraw-0.5.3}/docs/dev/hook-packages.md +8 -4
  21. {brkraw-0.5.2 → brkraw-0.5.3}/docs/getting-started/api.md +0 -2
  22. {brkraw-0.5.2 → brkraw-0.5.3}/pyproject.toml +1 -0
  23. {brkraw-0.5.2 → brkraw-0.5.3}/scripts/release_pr.py +45 -73
  24. brkraw-0.5.2/RELEASE_NOTES.md +0 -8
  25. {brkraw-0.5.2 → brkraw-0.5.3}/.github/DISCUSSION_TEMPLATE/proposal.yml +0 -0
  26. {brkraw-0.5.2 → brkraw-0.5.3}/.github/DISCUSSION_TEMPLATE/question.yml +0 -0
  27. {brkraw-0.5.2 → brkraw-0.5.3}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  28. {brkraw-0.5.2 → brkraw-0.5.3}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  29. {brkraw-0.5.2 → brkraw-0.5.3}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  30. {brkraw-0.5.2 → brkraw-0.5.3}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  31. {brkraw-0.5.2 → brkraw-0.5.3}/.github/copilot-instructions.md +0 -0
  32. {brkraw-0.5.2 → brkraw-0.5.3}/.github/workflows/ci.yml +0 -0
  33. {brkraw-0.5.2 → brkraw-0.5.3}/.github/workflows/docs.yml +0 -0
  34. {brkraw-0.5.2 → brkraw-0.5.3}/.github/workflows/publish.yml +0 -0
  35. {brkraw-0.5.2 → brkraw-0.5.3}/.github/workflows/release.yml +0 -0
  36. {brkraw-0.5.2 → brkraw-0.5.3}/.gitignore +0 -0
  37. {brkraw-0.5.2 → brkraw-0.5.3}/.markdownlint.yaml +0 -0
  38. {brkraw-0.5.2 → brkraw-0.5.3}/AGENTS.md +0 -0
  39. {brkraw-0.5.2 → brkraw-0.5.3}/CODE_OF_CONDUCT.md +0 -0
  40. {brkraw-0.5.2 → brkraw-0.5.3}/CONTRIBUTING.md +0 -0
  41. {brkraw-0.5.2 → brkraw-0.5.3}/LICENSE +0 -0
  42. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/apps/__init__.py +0 -0
  43. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/apps/addon/__init__.py +0 -0
  44. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/apps/addon/core.py +0 -0
  45. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/apps/addon/dependencies.py +0 -0
  46. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/apps/addon/installation.py +0 -0
  47. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/apps/addon/io.py +0 -0
  48. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/apps/hook/__init__.py +0 -0
  49. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/apps/hook/core.py +0 -0
  50. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/apps/loader/__init__.py +0 -0
  51. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/apps/loader/formatter.py +0 -0
  52. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/apps/loader/info/__init__.py +0 -0
  53. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/apps/loader/info/scan.py +0 -0
  54. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/apps/loader/info/scan.yaml +0 -0
  55. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/apps/loader/info/study.py +0 -0
  56. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/apps/loader/info/study.yaml +0 -0
  57. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/apps/loader/info/transform.py +0 -0
  58. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/cli/__init__.py +0 -0
  59. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/cli/commands/__init__.py +0 -0
  60. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/cli/commands/addon.py +0 -0
  61. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/cli/commands/config.py +0 -0
  62. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/cli/commands/info.py +0 -0
  63. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/cli/commands/init.py +0 -0
  64. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/cli/commands/params.py +0 -0
  65. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/cli/commands/prune.py +0 -0
  66. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/cli/hook_args.py +0 -0
  67. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/cli/main.py +0 -0
  68. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/cli/utils.py +0 -0
  69. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/core/__init__.py +0 -0
  70. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/core/config.py +0 -0
  71. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/core/entrypoints.py +0 -0
  72. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/core/formatter.py +0 -0
  73. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/core/fs.py +0 -0
  74. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/core/jcamp.py +0 -0
  75. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/core/layout.py +0 -0
  76. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/core/parameters.py +0 -0
  77. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/core/zip.py +0 -0
  78. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/dataclasses/__init__.py +0 -0
  79. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/dataclasses/node.py +0 -0
  80. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/dataclasses/reco.py +0 -0
  81. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/dataclasses/scan.py +0 -0
  82. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/dataclasses/study.py +0 -0
  83. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/default/__init__.py +0 -0
  84. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/default/pruner_specs/deid4share.yaml +0 -0
  85. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/default/rules/00_default.yaml +0 -0
  86. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/default/specs/metadata_dicom.yaml +0 -0
  87. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/default/specs/metadata_transforms.py +0 -0
  88. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/resolver/__init__.py +0 -0
  89. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/resolver/affine.py +0 -0
  90. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/resolver/datatype.py +0 -0
  91. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/resolver/fid.py +0 -0
  92. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/resolver/helpers.py +0 -0
  93. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/resolver/image.py +0 -0
  94. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/resolver/shape.py +0 -0
  95. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/schema/__init__.py +0 -0
  96. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/schema/context_map.yaml +0 -0
  97. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/schema/meta.yaml +0 -0
  98. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/schema/pruner.yaml +0 -0
  99. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/schema/remapper.yaml +0 -0
  100. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/schema/rules.yaml +0 -0
  101. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/specs/__init__.py +0 -0
  102. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/specs/hook/__init__.py +0 -0
  103. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/specs/hook/logic.py +0 -0
  104. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/specs/hook/validator.py +0 -0
  105. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/specs/meta/__init__.py +0 -0
  106. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/specs/meta/validator.py +0 -0
  107. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/specs/pruner/__init__.py +0 -0
  108. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/specs/pruner/logic.py +0 -0
  109. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/specs/pruner/validator.py +0 -0
  110. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/specs/remapper/__init__.py +0 -0
  111. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/specs/remapper/logic.py +0 -0
  112. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/specs/remapper/validator.py +0 -0
  113. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/specs/rules/__init__.py +0 -0
  114. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/specs/rules/logic.py +0 -0
  115. {brkraw-0.5.2 → brkraw-0.5.3}/brkraw/specs/rules/validator.py +0 -0
  116. {brkraw-0.5.2 → brkraw-0.5.3}/docs/api/addon.md +0 -0
  117. {brkraw-0.5.2 → brkraw-0.5.3}/docs/api/hook.md +0 -0
  118. {brkraw-0.5.2 → brkraw-0.5.3}/docs/api/info.md +0 -0
  119. {brkraw-0.5.2 → brkraw-0.5.3}/docs/api/layout.md +0 -0
  120. {brkraw-0.5.2 → brkraw-0.5.3}/docs/api/prune.md +0 -0
  121. {brkraw-0.5.2 → brkraw-0.5.3}/docs/assets/brkraw-logo-dark.svg +0 -0
  122. {brkraw-0.5.2 → brkraw-0.5.3}/docs/assets/brkraw-logo-light.svg +0 -0
  123. {brkraw-0.5.2 → brkraw-0.5.3}/docs/assets/brkraw-logo.svg +0 -0
  124. {brkraw-0.5.2 → brkraw-0.5.3}/docs/assets/favicon-16.png +0 -0
  125. {brkraw-0.5.2 → brkraw-0.5.3}/docs/assets/favicon-192.png +0 -0
  126. {brkraw-0.5.2 → brkraw-0.5.3}/docs/assets/favicon-32.png +0 -0
  127. {brkraw-0.5.2 → brkraw-0.5.3}/docs/assets/favicon-512.png +0 -0
  128. {brkraw-0.5.2 → brkraw-0.5.3}/docs/assets/favicon-dark.svg +0 -0
  129. {brkraw-0.5.2 → brkraw-0.5.3}/docs/assets/favicon-light.svg +0 -0
  130. {brkraw-0.5.2 → brkraw-0.5.3}/docs/assets/favicon.ico +0 -0
  131. {brkraw-0.5.2 → brkraw-0.5.3}/docs/assets/favicon.svg +0 -0
  132. {brkraw-0.5.2 → brkraw-0.5.3}/docs/assets/site.webmanifest +0 -0
  133. {brkraw-0.5.2 → brkraw-0.5.3}/docs/cli/addon.md +0 -0
  134. {brkraw-0.5.2 → brkraw-0.5.3}/docs/cli/config.md +0 -0
  135. {brkraw-0.5.2 → brkraw-0.5.3}/docs/cli/convert.md +0 -0
  136. {brkraw-0.5.2 → brkraw-0.5.3}/docs/cli/hook.md +0 -0
  137. {brkraw-0.5.2 → brkraw-0.5.3}/docs/cli/index.md +0 -0
  138. {brkraw-0.5.2 → brkraw-0.5.3}/docs/cli/info.md +0 -0
  139. {brkraw-0.5.2 → brkraw-0.5.3}/docs/cli/prune.md +0 -0
  140. {brkraw-0.5.2 → brkraw-0.5.3}/docs/dev/cli-extensions.md +0 -0
  141. {brkraw-0.5.2 → brkraw-0.5.3}/docs/dev/contributing.md +0 -0
  142. {brkraw-0.5.2 → brkraw-0.5.3}/docs/dev/core-vs-addon.md +0 -0
  143. {brkraw-0.5.2 → brkraw-0.5.3}/docs/dev/documentation.md +0 -0
  144. {brkraw-0.5.2 → brkraw-0.5.3}/docs/dev/roadmap.md +0 -0
  145. {brkraw-0.5.2 → brkraw-0.5.3}/docs/getting-started/backup.md +0 -0
  146. {brkraw-0.5.2 → brkraw-0.5.3}/docs/getting-started/bids.md +0 -0
  147. {brkraw-0.5.2 → brkraw-0.5.3}/docs/getting-started/cli.md +0 -0
  148. {brkraw-0.5.2 → brkraw-0.5.3}/docs/getting-started/configuration.md +0 -0
  149. {brkraw-0.5.2 → brkraw-0.5.3}/docs/getting-started/hooks.md +0 -0
  150. {brkraw-0.5.2 → brkraw-0.5.3}/docs/getting-started/index.md +0 -0
  151. {brkraw-0.5.2 → brkraw-0.5.3}/docs/getting-started/mrs.md +0 -0
  152. {brkraw-0.5.2 → brkraw-0.5.3}/docs/getting-started/viewer.md +0 -0
  153. {brkraw-0.5.2 → brkraw-0.5.3}/docs/index.md +0 -0
  154. {brkraw-0.5.2 → brkraw-0.5.3}/docs/overrides/404.html +0 -0
  155. {brkraw-0.5.2 → brkraw-0.5.3}/docs/overrides/partials/extrahead.html +0 -0
  156. {brkraw-0.5.2 → brkraw-0.5.3}/docs/reference/addons-and-plugins.md +0 -0
  157. {brkraw-0.5.2 → brkraw-0.5.3}/docs/reference/cli-extensions.md +0 -0
  158. {brkraw-0.5.2 → brkraw-0.5.3}/docs/reference/context-map.md +0 -0
  159. {brkraw-0.5.2 → brkraw-0.5.3}/docs/reference/extensibility.md +0 -0
  160. {brkraw-0.5.2 → brkraw-0.5.3}/docs/reference/hook-packages.md +0 -0
  161. {brkraw-0.5.2 → brkraw-0.5.3}/docs/reference/layout.md +0 -0
  162. {brkraw-0.5.2 → brkraw-0.5.3}/docs/reference/rules.md +0 -0
  163. {brkraw-0.5.2 → brkraw-0.5.3}/docs/reference/specs.md +0 -0
  164. {brkraw-0.5.2 → brkraw-0.5.3}/docs/stylesheets/extra.css +0 -0
  165. {brkraw-0.5.2 → brkraw-0.5.3}/mkdocs.yml +0 -0
  166. {brkraw-0.5.2 → brkraw-0.5.3}/scripts/cff_to_biblatex.py +0 -0
  167. {brkraw-0.5.2 → brkraw-0.5.3}/scripts/release_notes.py +0 -0
  168. {brkraw-0.5.2 → brkraw-0.5.3}/scripts/release_prep.py +0 -0
  169. {brkraw-0.5.2 → brkraw-0.5.3}/scripts/tag_and_push.py +0 -0
  170. {brkraw-0.5.2 → brkraw-0.5.3}/scripts/update_contributors.py +0 -0
  171. {brkraw-0.5.2 → brkraw-0.5.3}/scripts/update_readme_bibtex.py +0 -0
  172. {brkraw-0.5.2 → brkraw-0.5.3}/scripts/verify_release_version.py +0 -0
  173. {brkraw-0.5.2 → brkraw-0.5.3}/tests/conftest.py +0 -0
  174. {brkraw-0.5.2 → brkraw-0.5.3}/tests/helpers.py +0 -0
  175. {brkraw-0.5.2 → brkraw-0.5.3}/tests/test_01_core/__init__.py +0 -0
  176. {brkraw-0.5.2 → brkraw-0.5.3}/tests/test_01_core/fixtures/acqp_EPI_pv5_1.jdx +0 -0
  177. {brkraw-0.5.2 → brkraw-0.5.3}/tests/test_01_core/fixtures/method_EPI_pv5_1.jdx +0 -0
  178. {brkraw-0.5.2 → brkraw-0.5.3}/tests/test_01_core/fixtures/method_FLASH_pv360_3_1.jdx +0 -0
  179. {brkraw-0.5.2 → brkraw-0.5.3}/tests/test_01_core/test_formatter.py +0 -0
  180. {brkraw-0.5.2 → brkraw-0.5.3}/tests/test_01_core/test_fs.py +0 -0
  181. {brkraw-0.5.2 → brkraw-0.5.3}/tests/test_01_core/test_jcamp.py +0 -0
  182. {brkraw-0.5.2 → brkraw-0.5.3}/tests/test_01_core/test_parameters.py +0 -0
  183. {brkraw-0.5.2 → brkraw-0.5.3}/tests/test_01_core/test_resources.py +0 -0
  184. {brkraw-0.5.2 → brkraw-0.5.3}/tests/test_01_core/test_zip.py +0 -0
  185. {brkraw-0.5.2 → brkraw-0.5.3}/tests/test_02_dataclasses/test_dir-vs-zipped.py +0 -0
  186. {brkraw-0.5.2 → brkraw-0.5.3}/tests/test_03_resolver/test_affine.py +0 -0
  187. {brkraw-0.5.2 → brkraw-0.5.3}/tests/test_04_specs/test_context_map_cases.py +0 -0
  188. {brkraw-0.5.2 → brkraw-0.5.3}/tests/test_04_specs/test_remapper.py +0 -0
  189. {brkraw-0.5.2 → brkraw-0.5.3}/tests/test_apps/test_affine_post_transform.py +0 -0
  190. {brkraw-0.5.2 → brkraw-0.5.3}/tests/test_apps/test_loader_info_missing_visu_pars.py +0 -0
  191. {brkraw-0.5.2 → brkraw-0.5.3}/tests/test_cli/test_hook_args_yaml.py +0 -0
  192. {brkraw-0.5.2 → brkraw-0.5.3}/tests/test_cli/test_hook_preset.py +0 -0
  193. {brkraw-0.5.2 → brkraw-0.5.3}/tests/test_scripts/test_update_contributors.py +0 -0
@@ -29,11 +29,10 @@ jobs:
29
29
  import re
30
30
  from pathlib import Path
31
31
 
32
- text = Path("src/brkraw/__init__.py").read_text(encoding="utf-8")
32
+ text = Path("src/brkraw/__init__.py").read_text(encoding="utf-8").lstrip("\\ufeff")
33
33
  match = re.search(
34
- r"^\\s*__version__(?:\\s*:\\s*[^=]+)?\\s*=\\s*['\\\"]([^'\\\"]+)['\\\"]",
34
+ r"__version__(?:\s*:\s*[^=]+)?\s*=\s*['\"]([^'\"]+)['\"]",
35
35
  text,
36
- re.M,
37
36
  )
38
37
  if not match:
39
38
  raise SystemExit("No __version__ found in src/brkraw/__init__.py")
@@ -34,4 +34,4 @@ keywords:
34
34
  - BIDS
35
35
  - neuroimaging
36
36
 
37
- version: "0.5.2"
37
+ version: "0.5.3"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: brkraw
3
- Version: 0.5.2
3
+ Version: 0.5.3
4
4
  Summary: Toolkit for loading Bruker Paravision datasets, mapping metadata, and exporting NIfTI
5
5
  Project-URL: Homepage, https://brkraw.github.io
6
6
  Maintainer-email: SungHo Lee <shlee@unc.edu>
@@ -31,6 +31,7 @@ Requires-Dist: mkdocs; extra == 'dev'
31
31
  Requires-Dist: mkdocs-material; extra == 'dev'
32
32
  Requires-Dist: pymdown-extensions; extra == 'dev'
33
33
  Requires-Dist: pytest; extra == 'dev'
34
+ Requires-Dist: tomli; extra == 'dev'
34
35
  Provides-Extra: docs
35
36
  Requires-Dist: rich; extra == 'docs'
36
37
  Provides-Extra: minimal
@@ -48,7 +49,7 @@ Description-Content-Type: text/markdown
48
49
 
49
50
  A modular toolkit for Bruker MRI raw-data handling.
50
51
 
51
- BrkRaw (v0.5.2) converts raw data into standardized, neuroimaging-ready
52
+ BrkRaw (v0.5.3) converts raw data into standardized, neuroimaging-ready
52
53
  datasets, with extensible rules/specs and plugin hooks.
53
54
 
54
55
  - Documentation: [brkraw.github.io](https://brkraw.github.io/)
@@ -66,16 +67,14 @@ If you use BrkRaw in your research, please cite it.
66
67
 
67
68
  <!-- BEGIN: brkraw-bibtex -->
68
69
  ```biblatex
69
- @software{brkraw_2026,
70
- author = {Lee, Sung-Ho and Devenyi, Gabriel A and Ban, Woomi and Shih, Yen-Yu Ian},
70
+ @software{brkraw,
71
+ author = {Lee, Sung-Ho and Devenyi, Gabriel A. and Ban, Woomi and Shih, Yen-Yu Ian},
71
72
  title = {BrkRaw: A modular toolkit for Bruker MRI raw-data handling},
72
- year = {2026},
73
- version = {0.5.0},
73
+ version = {0.5.2},
74
74
  doi = {10.5281/zenodo.3818614},
75
75
  url = {https://github.com/BrkRaw/brkraw},
76
76
  note = {Documentation: https://brkraw.github.io},
77
- license = {GPL-3.0-only},
78
- date = {2026-01-13}
77
+ license = {GPL-3.0-only}
79
78
  }
80
79
  ```
81
80
  <!-- END: brkraw-bibtex -->
@@ -10,7 +10,7 @@
10
10
 
11
11
  A modular toolkit for Bruker MRI raw-data handling.
12
12
 
13
- BrkRaw (v0.5.2) converts raw data into standardized, neuroimaging-ready
13
+ BrkRaw (v0.5.3) converts raw data into standardized, neuroimaging-ready
14
14
  datasets, with extensible rules/specs and plugin hooks.
15
15
 
16
16
  - Documentation: [brkraw.github.io](https://brkraw.github.io/)
@@ -28,16 +28,14 @@ If you use BrkRaw in your research, please cite it.
28
28
 
29
29
  <!-- BEGIN: brkraw-bibtex -->
30
30
  ```biblatex
31
- @software{brkraw_2026,
32
- author = {Lee, Sung-Ho and Devenyi, Gabriel A and Ban, Woomi and Shih, Yen-Yu Ian},
31
+ @software{brkraw,
32
+ author = {Lee, Sung-Ho and Devenyi, Gabriel A. and Ban, Woomi and Shih, Yen-Yu Ian},
33
33
  title = {BrkRaw: A modular toolkit for Bruker MRI raw-data handling},
34
- year = {2026},
35
- version = {0.5.0},
34
+ version = {0.5.2},
36
35
  doi = {10.5281/zenodo.3818614},
37
36
  url = {https://github.com/BrkRaw/brkraw},
38
37
  note = {Documentation: https://brkraw.github.io},
39
- license = {GPL-3.0-only},
40
- date = {2026-01-13}
38
+ license = {GPL-3.0-only}
41
39
  }
42
40
  ```
43
41
  <!-- END: brkraw-bibtex -->
@@ -0,0 +1,13 @@
1
+ # Release v0.5.3
2
+
3
+ Date: 2026-01-21
4
+ Changes since 0.5.2
5
+
6
+ - fix: avoid gh pr graphql in release_pr (6311e09)
7
+ - docs: release notes for v0.5.3 (2e427de)
8
+ - chore: prepare release v0.5.3 (15e1158)
9
+ - docs: update contributors (83d68bf)
10
+ - Add debug logging for converter hooks (db8943d)
11
+ - refactor: drop flip_x from nifti header (14e5304)
12
+ - refactor: route hook kwargs by signature and drop format option (4c3f4d6)
13
+ - readme.md biblatex update (b39e11d)
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = '0.5.2'
3
+ __version__ = '0.5.3'
4
4
  from .apps.loader import BrukerLoader
5
5
 
6
6
 
@@ -163,6 +163,7 @@ class BrukerLoader:
163
163
  scan.convert = MethodType(_convert, scan)
164
164
  scan._converter_hook = None
165
165
  scan._converter_hook_name = None
166
+ scan.converter_func = None
166
167
  if rules:
167
168
  try:
168
169
  hook_name = select_rule_use(
@@ -259,9 +260,8 @@ class BrukerLoader:
259
260
  partial(_get_affine, decimals=self._affine_decimals),
260
261
  scan,
261
262
  )
262
- scan.get_nifti1image = MethodType(_get_nifti1image, scan)
263
- scan.convert = MethodType(_convert, scan)
264
263
  scan._converter_hook = None
264
+ scan.converter_func = None
265
265
 
266
266
  def get_scan(self, scan_id: int) -> "ScanLoader":
267
267
  """Return scan by id.
@@ -349,7 +349,6 @@ class BrukerLoader:
349
349
  override_header: Optional[Nifti1HeaderContents] = None,
350
350
  override_subject_type: Optional[SubjectType] = None,
351
351
  override_subject_pose: Optional[SubjectPose] = None,
352
- flip_x: bool = False,
353
352
  flatten_fg: bool = False,
354
353
  xyz_units: XYZUNIT = 'mm',
355
354
  t_units: TUNIT = 'sec'):
@@ -362,7 +361,6 @@ class BrukerLoader:
362
361
  override_header: Optional header values to apply.
363
362
  override_subject_type: Subject type override for subject view.
364
363
  override_subject_pose: Subject pose override for subject view.
365
- flip_x: If True, set NIfTI header x-flip flag.
366
364
  xyz_units: Spatial units for NIfTI header.
367
365
  t_units: Temporal units for NIfTI header.
368
366
 
@@ -372,12 +370,10 @@ class BrukerLoader:
372
370
  scan = self.get_scan(scan_id)
373
371
  return scan.convert(
374
372
  reco_id,
375
- format="nifti",
376
373
  space=space,
377
374
  override_header=override_header,
378
375
  override_subject_type=override_subject_type,
379
376
  override_subject_pose=override_subject_pose,
380
- flip_x=flip_x,
381
377
  flatten_fg=flatten_fg,
382
378
  xyz_units=xyz_units,
383
379
  t_units=t_units,
@@ -388,27 +384,23 @@ class BrukerLoader:
388
384
  scan_id: int,
389
385
  reco_id: Optional[int] = None,
390
386
  *,
391
- format: Literal["nifti", "nifti1"] = "nifti",
392
387
  space: AffineSpace = 'subject_ras',
393
388
  override_header: Optional[Nifti1HeaderContents] = None,
394
389
  override_subject_type: Optional[SubjectType] = None,
395
390
  override_subject_pose: Optional[SubjectPose] = None,
396
- flip_x: bool = False,
397
391
  flatten_fg: bool = False,
398
392
  xyz_units: XYZUNIT = "mm",
399
393
  t_units: TUNIT = "sec",
400
394
  hook_args_by_name: Optional[Mapping[str, Mapping[str, Any]]] = None,
401
395
  ):
402
- """Convert a scan/reco to the requested output format."""
396
+ """Convert a scan/reco to output object(s) supporting to_filename()."""
403
397
  scan = self.get_scan(scan_id)
404
398
  return scan.convert(
405
399
  reco_id,
406
- format=format,
407
400
  space=space,
408
401
  override_header=override_header,
409
402
  override_subject_type=override_subject_type,
410
403
  override_subject_pose=override_subject_pose,
411
- flip_x=flip_x,
412
404
  flatten_fg=flatten_fg,
413
405
  xyz_units=xyz_units,
414
406
  t_units=t_units,
@@ -21,7 +21,7 @@ from ...core.parameters import Parameters
21
21
  from ...specs.remapper import load_spec, map_parameters, load_context_map, apply_context_map
22
22
  from ...specs.rules import load_rules, select_rule_use
23
23
  from ...dataclasses import Reco, Scan, Study
24
- from .types import ScanLoader
24
+ from .types import ScanLoader, ToFilename, ConvertType, GetDataobjType, GetAffineType
25
25
  from ...specs import hook as converter_core
26
26
  from ...resolver import affine as affine_resolver
27
27
  from ...resolver import image as image_resolver
@@ -472,6 +472,54 @@ def _apply_affine_post_transform(affines: AffineReturn, *, kwargs: Mapping[str,
472
472
 
473
473
 
474
474
  def get_nifti1image(
475
+ self: Union["Scan", "ScanLoader"],
476
+ reco_id: int,
477
+ dataobjs: Tuple[np.ndarray, ...],
478
+ affines: Tuple[np.ndarray, ...],
479
+ *,
480
+ xyz_units: XYZUNIT = "mm",
481
+ t_units: TUNIT = "sec",
482
+ override_header: Optional[Nifti1HeaderContents] = None,
483
+ ) -> Optional[Union[Tuple["Nifti1Image", ...], "Nifti1Image"]]:
484
+ """Return NIfTI image(s) for a reco.
485
+
486
+ Args:
487
+ self: Scan or ScanLoader instance.
488
+ reco_id: Reco identifier to read (defaults to the first available).
489
+ xyz_units: Spatial units for NIfTI header.
490
+ t_units: Temporal units for NIfTI header.
491
+ override_header: Optional header values to apply.
492
+
493
+ Returns:
494
+ Output object(s) supporting to_filename(). Returns None when required
495
+ metadata is unavailable.
496
+ """
497
+ self = cast(ScanLoader, self)
498
+
499
+ image_info = self.image_info.get(reco_id)
500
+ if dataobjs is None or affines is None or image_info is None:
501
+ return None
502
+
503
+ niiobjs = []
504
+ for i, dataobj in enumerate(dataobjs):
505
+ affine = affines[i]
506
+ niiobj = Nifti1Image(dataobj, affine)
507
+ nifti1header_contents = nifti_resolver.resolve(
508
+ image_info, xyz_units=xyz_units, t_units=t_units
509
+ )
510
+ if override_header:
511
+ for key, value in override_header.items():
512
+ if value is not None:
513
+ nifti1header_contents[key] = value
514
+ niiobj = nifti_resolver.update(niiobj, nifti1header_contents)
515
+ niiobjs.append(niiobj)
516
+
517
+ if len(niiobjs) == 1:
518
+ return niiobjs[0]
519
+ return tuple(niiobjs)
520
+
521
+
522
+ def convert(
475
523
  self: Union["Scan", "ScanLoader"],
476
524
  reco_id: Optional[int] = None,
477
525
  *,
@@ -479,30 +527,30 @@ def get_nifti1image(
479
527
  override_header: Optional[Nifti1HeaderContents] = None,
480
528
  override_subject_type: Optional[SubjectType] = None,
481
529
  override_subject_pose: Optional[SubjectPose] = None,
482
- flip_x: bool = False,
483
530
  flatten_fg: bool = False,
484
531
  xyz_units: XYZUNIT = "mm",
485
532
  t_units: TUNIT = "sec",
486
533
  hook_args_by_name: Optional[Mapping[str, Mapping[str, Any]]] = None,
487
- ) -> Optional[Union[Tuple["Nifti1Image", ...], "Nifti1Image"]]:
488
- """Return NIfTI image(s) for a reco.
489
-
534
+ **kwargs: Any,
535
+ ) -> Optional[Union["ToFilename", Tuple["ToFilename", ...]]]:
536
+ """Convert a reco to output object(s).
537
+
490
538
  Args:
491
- self: Scan or ScanLoader instance.
492
- reco_id: Reco identifier to read (defaults to the first available).
493
539
  space: Output affine space ("raw", "scanner", "subject_ras").
494
540
  override_header: Optional header values to apply.
495
541
  override_subject_type: Subject type override for subject-view wrapping.
496
542
  override_subject_pose: Subject pose override for subject-view wrapping.
497
- flip_x: If True, set NIfTI header x-flip flag.
543
+ flatten_fg: If True, flatten foreground dimensions.
544
+ xyz_units: Spatial units for NIfTI header.
545
+ t_units: Temporal units for NIfTI header.
546
+ hook_args_by_name: Optional hook args mapping (split per helper signature).
547
+ flatten_fg: If True, flatten foreground dimensions.
498
548
  xyz_units: Spatial units for NIfTI header.
499
549
  t_units: Temporal units for NIfTI header.
500
-
501
550
  Returns:
502
551
  Single NIfTI image when one slice pack exists; otherwise a tuple of
503
552
  images. Returns None when required metadata is unavailable.
504
553
  """
505
-
506
554
  if not all(
507
555
  hasattr(self, attr) for attr in ["image_info", "affine_info", "get_dataobj", "get_affine"]
508
556
  ):
@@ -512,14 +560,57 @@ def get_nifti1image(
512
560
  resolved_reco_id = _resolve_reco_id(self, reco_id)
513
561
  if resolved_reco_id is None:
514
562
  return None
563
+
564
+ hook_name = getattr(self, "_converter_hook_name", None)
565
+ if isinstance(hook_name, str) and hook_name:
566
+ logger.debug(
567
+ "Convert starting for scan %s reco %s with hook %s",
568
+ getattr(self, "scan_id", "?"),
569
+ resolved_reco_id,
570
+ hook_name,
571
+ )
572
+ else:
573
+ logger.debug(
574
+ "Convert starting for scan %s reco %s (no hook)",
575
+ getattr(self, "scan_id", "?"),
576
+ resolved_reco_id,
577
+ )
578
+
515
579
  hook_kwargs = _resolve_hook_kwargs(self, hook_args_by_name)
516
580
  data_kwargs = _filter_hook_kwargs(self.get_dataobj, hook_kwargs)
581
+ convert_kwargs = {
582
+ key: value
583
+ for key, value in hook_kwargs.items()
584
+ if key not in data_kwargs
585
+ }
517
586
  if data_kwargs:
587
+ logger.debug(
588
+ "Calling get_dataobj for scan %s reco %s with args %s",
589
+ getattr(self, "scan_id", "?"),
590
+ resolved_reco_id,
591
+ data_kwargs,
592
+ )
518
593
  dataobjs = self.get_dataobj(resolved_reco_id, **data_kwargs)
519
594
  else:
595
+ logger.debug(
596
+ "Calling get_dataobj for scan %s reco %s (no args)",
597
+ getattr(self, "scan_id", "?"),
598
+ resolved_reco_id,
599
+ )
520
600
  dataobjs = self.get_dataobj(resolved_reco_id)
521
601
  affine_kwargs = _filter_hook_kwargs(self.get_affine, hook_kwargs)
602
+ convert_kwargs = {
603
+ key: value
604
+ for key, value in convert_kwargs.items()
605
+ if key not in affine_kwargs
606
+ }
522
607
  if affine_kwargs:
608
+ logger.debug(
609
+ "Calling get_affine for scan %s reco %s with args %s",
610
+ getattr(self, "scan_id", "?"),
611
+ resolved_reco_id,
612
+ affine_kwargs,
613
+ )
523
614
  affines = self.get_affine(
524
615
  resolved_reco_id,
525
616
  space=space,
@@ -528,77 +619,64 @@ def get_nifti1image(
528
619
  **affine_kwargs,
529
620
  )
530
621
  else:
622
+ logger.debug(
623
+ "Calling get_affine for scan %s reco %s (no args)",
624
+ getattr(self, "scan_id", "?"),
625
+ resolved_reco_id,
626
+ )
531
627
  affines = self.get_affine(
532
628
  resolved_reco_id,
533
629
  space=space,
534
630
  override_subject_type=override_subject_type,
535
631
  override_subject_pose=override_subject_pose,
536
632
  )
537
- image_info = self.image_info.get(resolved_reco_id)
538
-
539
- if dataobjs is None or affines is None or image_info is None:
633
+
634
+ if dataobjs is None or affines is None:
540
635
  return None
541
-
542
- if not isinstance(dataobjs, tuple) and not isinstance(affines, tuple):
636
+
637
+ if not isinstance(dataobjs, tuple):
543
638
  dataobjs = (dataobjs,)
639
+ if not isinstance(affines, tuple):
544
640
  affines = (affines,)
545
-
546
- niiobjs = []
641
+
642
+ dataobjs = list(dataobjs)
547
643
  for i, dataobj in enumerate(dataobjs):
548
644
  if flatten_fg and dataobj.ndim > 4:
549
645
  spatial_shape = dataobj.shape[:3]
550
646
  flattened = int(np.prod(dataobj.shape[3:]))
551
- dataobj = dataobj.reshape((*spatial_shape, flattened), order="A")
552
- affine = affines[i]
553
- niiobj = Nifti1Image(dataobj, affine)
554
- nifti1header_contents = nifti_resolver.resolve(
555
- image_info, flip_x=flip_x, xyz_units=xyz_units, t_units=t_units
647
+ dataobjs[i] = dataobj.reshape((*spatial_shape, flattened), order="A")
648
+ dataobjs = tuple(dataobjs)
649
+
650
+ converter_func = getattr(self, "converter_func", None)
651
+ if isinstance(converter_func, ConvertType):
652
+ hook_call_kwargs = _filter_hook_kwargs(converter_func, convert_kwargs)
653
+ logger.debug(
654
+ "Calling converter hook for scan %s reco %s with args %s",
655
+ getattr(self, "scan_id", "?"),
656
+ resolved_reco_id,
657
+ hook_call_kwargs,
658
+ )
659
+ return converter_func(
660
+ dataobj=dataobjs,
661
+ affine=affines,
662
+ **hook_call_kwargs,
556
663
  )
557
- if override_header:
558
- for key, value in override_header.items():
559
- if value is not None:
560
- nifti1header_contents[key] = value
561
- niiobj = nifti_resolver.update(niiobj, nifti1header_contents)
562
- niiobjs.append(niiobj)
563
-
564
- if len(niiobjs) == 1:
565
- return niiobjs[0]
566
- return tuple(niiobjs)
567
-
568
664
 
569
- def convert(
570
- self: Union["Scan", "ScanLoader"],
571
- reco_id: Optional[int] = None,
572
- *,
573
- format: Literal["nifti", "nifti1"] = "nifti",
574
- space: AffineSpace = "subject_ras",
575
- override_header: Optional[Nifti1HeaderContents] = None,
576
- override_subject_type: Optional[SubjectType] = None,
577
- override_subject_pose: Optional[SubjectPose] = None,
578
- flip_x: bool = False,
579
- flatten_fg: bool = False,
580
- xyz_units: XYZUNIT = "mm",
581
- t_units: TUNIT = "sec",
582
- hook_args_by_name: Optional[Mapping[str, Mapping[str, Any]]] = None,
583
- ) -> Optional[Union[Tuple["Nifti1Image", ...], "Nifti1Image"]]:
584
- """Convert a reco to a selected output format."""
585
- if format not in {"nifti", "nifti1"}:
586
- raise ValueError(f"Unsupported format: {format}")
665
+ nifti1image_kwargs = {
666
+ "xyz_units": xyz_units,
667
+ "t_units": t_units,
668
+ "override_header": override_header,
669
+ **kwargs,
670
+ }
671
+ nifti1image_kwargs = _filter_hook_kwargs(get_nifti1image, nifti1image_kwargs)
587
672
  return get_nifti1image(
588
673
  self,
589
- reco_id,
590
- space=space,
591
- override_header=override_header,
592
- override_subject_type=override_subject_type,
593
- override_subject_pose=override_subject_pose,
594
- flip_x=flip_x,
595
- flatten_fg=flatten_fg,
596
- xyz_units=xyz_units,
597
- t_units=t_units,
598
- hook_args_by_name=hook_args_by_name,
674
+ reco_id=resolved_reco_id,
675
+ dataobjs=dataobjs,
676
+ affines=affines,
677
+ **nifti1image_kwargs,
599
678
  )
600
679
 
601
-
602
680
  def _resolve_hook_kwargs(
603
681
  scan: Union["Scan", "ScanLoader"],
604
682
  hook_args_by_name: Optional[Mapping[str, Mapping[str, Any]]],
@@ -608,6 +686,12 @@ def _resolve_hook_kwargs(
608
686
  hook_name = getattr(scan, "_converter_hook_name", None)
609
687
  if not isinstance(hook_name, str) or not hook_name:
610
688
  return {}
689
+ logger.debug(
690
+ "Resolving hook args for scan %s hook %s (available: %s)",
691
+ getattr(scan, "scan_id", "?"),
692
+ hook_name,
693
+ sorted(hook_args_by_name.keys()),
694
+ )
611
695
  values = hook_args_by_name.get(hook_name)
612
696
  if values is None:
613
697
  seen: set[str] = set()
@@ -643,7 +727,12 @@ def _resolve_hook_kwargs(
643
727
  )
644
728
  values = candidate_values
645
729
  break
646
- return dict(values) if isinstance(values, Mapping) else {}
730
+ resolved = dict(values) if isinstance(values, Mapping) else {}
731
+ if resolved:
732
+ logger.debug("Resolved hook args for %s: %s", hook_name, resolved)
733
+ else:
734
+ logger.debug("No hook args resolved for %s.", hook_name)
735
+ return resolved
647
736
 
648
737
 
649
738
  def _filter_hook_kwargs(func: Any, hook_kwargs: Mapping[str, Any]) -> Dict[str, Any]:
@@ -785,6 +874,17 @@ def apply_converter_hook(
785
874
  """Override scan conversion helpers using a converter hook."""
786
875
  converter_core.validate_hook(converter_hook)
787
876
  plugin = dict(converter_hook)
877
+ logger.debug(
878
+ "Binding converter hook for scan %s: %s",
879
+ getattr(scan, "scan_id", "?"),
880
+ sorted(plugin.keys()),
881
+ )
882
+ if "get_dataobj" in plugin and not isinstance(plugin["get_dataobj"], GetDataobjType):
883
+ raise TypeError("Converter hook 'get_dataobj' must match GetDataobjType.")
884
+ if "get_affine" in plugin and not isinstance(plugin["get_affine"], GetAffineType):
885
+ raise TypeError("Converter hook 'get_affine' must match GetAffineType.")
886
+ if "convert" in plugin and not isinstance(plugin["convert"], ConvertType):
887
+ raise TypeError("Converter hook 'convert' must match ConvertType.")
788
888
  scan._converter_hook = plugin
789
889
  if "get_dataobj" in plugin:
790
890
  scan.get_dataobj = MethodType(plugin["get_dataobj"], scan)
@@ -794,4 +894,11 @@ def apply_converter_hook(
794
894
  get_affine = partial(get_affine, decimals=affine_decimals)
795
895
  scan.get_affine = MethodType(get_affine, scan)
796
896
  if "convert" in plugin:
797
- scan.convert = MethodType(plugin["convert"], scan)
897
+ scan.converter_func = MethodType(plugin["convert"], scan)
898
+ else:
899
+ scan.converter_func = None
900
+ logger.debug(
901
+ "Converter hook bound for scan %s (hook=%s)",
902
+ getattr(scan, "scan_id", "?"),
903
+ getattr(scan, "_converter_hook_name", None),
904
+ )
@@ -5,7 +5,7 @@ Last updated: 2025-12-30
5
5
 
6
6
  from __future__ import annotations
7
7
 
8
- from typing import Any, Union, Tuple, Dict, Optional, Protocol, Literal, Mapping, Callable, List, TYPE_CHECKING
8
+ from typing import Any, Union, Tuple, Dict, Optional, Protocol, Literal, Mapping, Callable, List, TYPE_CHECKING, runtime_checkable
9
9
  if TYPE_CHECKING:
10
10
  from typing_extensions import ParamSpec, TypeAlias
11
11
  else:
@@ -35,6 +35,7 @@ AffineSpace = Literal["raw", "scanner", "subject_ras"]
35
35
  P = ParamSpec("P")
36
36
 
37
37
 
38
+ @runtime_checkable
38
39
  class GetDataobjType(Protocol[P]):
39
40
  """Callable signature for get_dataobj overrides."""
40
41
  def __call__(
@@ -47,6 +48,7 @@ class GetDataobjType(Protocol[P]):
47
48
  ...
48
49
 
49
50
 
51
+ @runtime_checkable
50
52
  class GetAffineType(Protocol):
51
53
  """Callable signature for get_affine overrides."""
52
54
  def __call__(
@@ -63,44 +65,21 @@ class GetAffineType(Protocol):
63
65
  ...
64
66
 
65
67
 
66
- class GetNifti1ImageType(Protocol):
67
- """Callable signature for get_nifti1image overrides."""
68
- def __call__(
69
- self,
70
- scan: "Scan",
71
- reco_id: Optional[int] = None,
72
- *,
73
- override_header: Optional[Union[dict, "Nifti1HeaderContents"]],
74
- space: AffineSpace,
75
- override_subject_type: Optional[SubjectType],
76
- override_subject_pose: Optional[SubjectPose],
77
- flip_x: bool,
78
- flatten_fg: bool,
79
- xyz_units: XYZUNIT,
80
- t_units: TUNIT,
81
- **kwargs: Any,
82
- ) -> Optional[Union[Tuple["Nifti1Image", ...], "Nifti1Image"]]:
83
- ...
84
-
85
-
68
+ @runtime_checkable
86
69
  class ConvertType(Protocol):
87
70
  """Callable signature for convert overrides."""
88
71
  def __call__(
89
72
  self,
90
73
  scan: "Scan",
91
- reco_id: Optional[int] = None,
92
- *,
93
- format: Union[Literal["nifti", "nifti1"], str],
94
- override_header: Optional[Union[dict, "Nifti1HeaderContents"]],
95
- space: AffineSpace,
96
- override_subject_type: Optional[SubjectType],
97
- override_subject_pose: Optional[SubjectPose],
98
- flip_x: bool,
99
- flatten_fg: bool,
100
- xyz_units: XYZUNIT,
101
- t_units: TUNIT,
74
+ dataobj: Union[Tuple["np.ndarray", ...], "np.ndarray"],
75
+ affine: Union[Tuple["np.ndarray", ...], "np.ndarray"],
102
76
  **kwargs: Any,
103
- ) -> Optional[Union[Tuple["Nifti1Image", ...], "Nifti1Image"]]:
77
+ ) -> Optional[Union["ToFilename", Tuple["ToFilename", ...]]]:
78
+ ...
79
+
80
+ class ToFilename(Protocol):
81
+ """Result object that can be written to disk."""
82
+ def to_filename(self, filename: Union[str, "Path"], *args: Any, **kwargs: Any) -> Any:
104
83
  ...
105
84
 
106
85
 
@@ -126,9 +105,11 @@ class ScanLoader(Scan, BaseLoader):
126
105
 
127
106
  image_info: Dict[int, Optional["ResolvedImage"]]
128
107
  affine_info: Dict[int, Optional["ResolvedAffine"]]
108
+ converter_func: Optional[ConvertType]
129
109
  _converter_hook: Optional[ConverterHook]
130
110
  _converter_hook_name: Optional[str]
131
-
111
+
112
+
132
113
  def get_fid(self,
133
114
  buffer_start: Optional[int],
134
115
  buffer_size: Optional[int],
@@ -155,15 +136,12 @@ class ScanLoader(Scan, BaseLoader):
155
136
  ...
156
137
 
157
138
  def get_nifti1image(
158
- self,
159
- reco_id: Optional[int] = None,
139
+ self,
140
+ reco_id: int,
141
+ dataobjs: Tuple["np.ndarray", ...],
142
+ affines: Tuple["np.ndarray", ...],
160
143
  *,
161
144
  override_header: Optional[Union[dict, "Nifti1HeaderContents"]],
162
- space: AffineSpace = "subject_ras",
163
- override_subject_type: Optional[SubjectType],
164
- override_subject_pose: Optional[SubjectPose],
165
- flip_x: bool,
166
- flatten_fg: bool,
167
145
  xyz_units: XYZUNIT,
168
146
  t_units: TUNIT
169
147
  ) -> Optional[Union[Tuple["Nifti1Image", ...], "Nifti1Image"]]:
@@ -173,17 +151,16 @@ class ScanLoader(Scan, BaseLoader):
173
151
  self,
174
152
  reco_id: Optional[int] = None,
175
153
  *,
176
- format: Literal["nifti", "nifti1"],
177
- override_header: Optional[Union[dict, "Nifti1HeaderContents"]],
178
154
  space: AffineSpace = "subject_ras",
155
+ override_header: Optional[Union[dict, "Nifti1HeaderContents"]],
179
156
  override_subject_type: Optional[SubjectType],
180
157
  override_subject_pose: Optional[SubjectPose],
181
- flip_x: bool,
182
158
  flatten_fg: bool,
183
159
  xyz_units: XYZUNIT,
184
160
  t_units: TUNIT,
185
161
  hook_args_by_name: Optional[Mapping[str, Mapping[str, Any]]] = None,
186
- ) -> Optional[Union[Tuple["Nifti1Image", ...], "Nifti1Image"]]:
162
+ **kwargs: Any,
163
+ ) -> Optional[Union["ToFilename", Tuple["ToFilename", ...]]]:
187
164
  ...
188
165
 
189
166
  def get_metadata(
@@ -201,15 +178,15 @@ class RecoLoader(Reco, BaseLoader):
201
178
  ...
202
179
 
203
180
 
204
- ConverterHook: TypeAlias = Mapping[str, Union[GetDataobjType[Any], GetAffineType, GetNifti1ImageType, ConvertType]]
181
+ ConverterHook: TypeAlias = Mapping[str, Union[GetDataobjType[Any], GetAffineType, ConvertType]]
205
182
  """Mapping of converter hook keys to override callables."""
206
183
 
207
184
 
208
185
  __all__ = [
209
186
  'GetDataobjType',
210
187
  'GetAffineType',
211
- 'GetNifti1ImageType',
212
188
  'ConvertType',
189
+ 'ToFilename',
213
190
  'ConverterHook',
214
191
  'StudyLoader',
215
192
  'ScanLoader',