bioimage-cpp 0.4.0__tar.gz → 0.5.0__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 (291) hide show
  1. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/PKG-INFO +1 -1
  2. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/transformation/affine.hxx +37 -48
  3. bioimage_cpp-0.5.0/include/bioimage_cpp/transformation/coordinate.hxx +129 -0
  4. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bindings/transformation.cxx +112 -0
  5. bioimage_cpp-0.5.0/src/bioimage_cpp/_version.py +1 -0
  6. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bioimage_cpp/transformation/__init__.py +2 -0
  7. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bioimage_cpp/transformation/_transformation.py +106 -0
  8. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/test_transformation.py +121 -0
  9. bioimage_cpp-0.4.0/src/bioimage_cpp/_version.py +0 -1
  10. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/.github/workflows/docs.yml +0 -0
  11. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/.github/workflows/tests.yml +0 -0
  12. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/.github/workflows/wheels.yml +0 -0
  13. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/.gitignore +0 -0
  14. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/AGENTS.md +0 -0
  15. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/CMakeLists.txt +0 -0
  16. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/LICENSE +0 -0
  17. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/MIGRATION_GUIDE.md +0 -0
  18. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/README.md +0 -0
  19. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/affinities/check_compute_affinities.py +0 -0
  20. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/affinities/check_compute_embedding_distances.py +0 -0
  21. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/distance/benchmark.py +0 -0
  22. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/distance/check_non_maximum_distance_suppression.py +0 -0
  23. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/filters/PERFORMANCE_NOTES.md +0 -0
  24. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/filters/_bench_utils.py +0 -0
  25. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/filters/benchmark.py +0 -0
  26. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/filters/check_parity.py +0 -0
  27. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/flow/PERFORMANCE_NOTES.md +0 -0
  28. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/flow/_reference_impl.py +0 -0
  29. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/flow/benchmark.py +0 -0
  30. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/flow/check_flow_density.py +0 -0
  31. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/flow/create_test_data.py +0 -0
  32. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/graph/_grid_affinity_compatibility.py +0 -0
  33. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/graph/_rag_compatibility.py +0 -0
  34. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/graph/agglomeration/PERFORMANCE_NOTES.md +0 -0
  35. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/graph/agglomeration/_compatibility.py +0 -0
  36. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/graph/agglomeration/check_edge_weighted.py +0 -0
  37. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/graph/agglomeration/check_gasp.py +0 -0
  38. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/graph/agglomeration/check_mala.py +0 -0
  39. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/graph/agglomeration/check_node_and_edge_weighted.py +0 -0
  40. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/graph/agglomeration/diagnose.py +0 -0
  41. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/graph/benchmark_accumulate_labels.py +0 -0
  42. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/graph/benchmark_bfs.py +0 -0
  43. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/graph/check_grid_affinity_edges.py +0 -0
  44. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/graph/check_grid_affinity_lifted_edges.py +0 -0
  45. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/graph/check_rag_2d.py +0 -0
  46. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/graph/check_rag_3d.py +0 -0
  47. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/graph/lifted_multicut/PERFORMANCE_NOTES.md +0 -0
  48. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/graph/lifted_multicut/_compatibility.py +0 -0
  49. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/graph/lifted_multicut/check_fusion_move.py +0 -0
  50. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/graph/lifted_multicut/check_greedy_additive.py +0 -0
  51. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/graph/lifted_multicut/check_kernighan_lin.py +0 -0
  52. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/graph/lifted_multicut/evaluate_solvers.py +0 -0
  53. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/graph/lifted_multicut/repro_lifted_edges_segfault.py +0 -0
  54. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/graph/multicut/PERFORMANCE_NOTES.md +0 -0
  55. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/graph/multicut/_compatibility.py +0 -0
  56. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/graph/multicut/check_chained.py +0 -0
  57. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/graph/multicut/check_decomposer.py +0 -0
  58. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/graph/multicut/check_fusion_move.py +0 -0
  59. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/graph/multicut/check_greedy_additive.py +0 -0
  60. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/graph/multicut/check_greedy_fixation.py +0 -0
  61. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/graph/multicut/check_kernighan_lin.py +0 -0
  62. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/graph/multicut/evaluate_solvers.py +0 -0
  63. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/graph/mutex_watershed/check_mutex_clustering.py +0 -0
  64. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/graph/mutex_watershed/check_semantic_mutex_clustering.py +0 -0
  65. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/label_multiset/benchmark.py +0 -0
  66. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/local_maxima/benchmark.py +0 -0
  67. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/segmentation/PERFORMANCE_NOTES.md +0 -0
  68. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/segmentation/_label_equivalence.py +0 -0
  69. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/segmentation/_mutex_watershed_equivalence.py +0 -0
  70. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/segmentation/_semantic_mws_equivalence.py +0 -0
  71. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/segmentation/_watershed_equivalence.py +0 -0
  72. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/segmentation/_watershed_from_affinities_equivalence.py +0 -0
  73. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/segmentation/benchmark_mutex_watershed.py +0 -0
  74. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/segmentation/check_label_2d.py +0 -0
  75. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/segmentation/check_label_3d.py +0 -0
  76. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/segmentation/check_mutex_watershed_2d.py +0 -0
  77. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/segmentation/check_mutex_watershed_3d.py +0 -0
  78. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/segmentation/check_relabel_sequential.py +0 -0
  79. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/segmentation/check_semantic_mutex_watershed_2d.py +0 -0
  80. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/segmentation/check_semantic_mutex_watershed_3d.py +0 -0
  81. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/segmentation/check_watershed_2d.py +0 -0
  82. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/segmentation/check_watershed_3d.py +0 -0
  83. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/segmentation/check_watershed_from_affinities_2d.py +0 -0
  84. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/segmentation/check_watershed_from_affinities_3d.py +0 -0
  85. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/transformation/PERFORMANCE_NOTES.md +0 -0
  86. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/transformation/check_affine.py +0 -0
  87. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/utils/_mesh_smoothing_reference.py +0 -0
  88. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/utils/benchmark_mesh_smoothing.py +0 -0
  89. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/development/utils/benchmark_union_find.py +0 -0
  90. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/examples/segmentation/_lifted_problem.py +0 -0
  91. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/examples/segmentation/lifted_multicut_from_affinities.py +0 -0
  92. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/examples/segmentation/multicut_from_affinities.py +0 -0
  93. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/examples/segmentation/mutex_watershed.py +0 -0
  94. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/examples/segmentation/serialize_grid_lifted_problem.py +0 -0
  95. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/examples/segmentation/serialize_lifted_problem.py +0 -0
  96. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/examples/segmentation/watershed.py +0 -0
  97. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/affinities/compute_affinities.hxx +0 -0
  98. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/affinities/compute_embedding_distances.hxx +0 -0
  99. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/array_view.hxx +0 -0
  100. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/blocking.hxx +0 -0
  101. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/detail/edge_hash.hxx +0 -0
  102. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/detail/grid.hxx +0 -0
  103. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/detail/indexed_heap.hxx +0 -0
  104. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/detail/mutex_storage.hxx +0 -0
  105. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/detail/profile.hxx +0 -0
  106. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/detail/relabel.hxx +0 -0
  107. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/detail/semantic_labels.hxx +0 -0
  108. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/detail/threading.hxx +0 -0
  109. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/distance_transform.hxx +0 -0
  110. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/filters/convolve.hxx +0 -0
  111. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/filters/eigenvalues.hxx +0 -0
  112. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/filters/gaussian.hxx +0 -0
  113. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/filters/kernel.hxx +0 -0
  114. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/flow/flow_density.hxx +0 -0
  115. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/agglomeration/agglomerative_clustering.hxx +0 -0
  116. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/agglomeration/cluster_policy_base.hxx +0 -0
  117. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/agglomeration/detail.hxx +0 -0
  118. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/agglomeration/edge_weighted.hxx +0 -0
  119. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/agglomeration/gasp.hxx +0 -0
  120. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/agglomeration/mala.hxx +0 -0
  121. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/agglomeration/node_and_edge_weighted.hxx +0 -0
  122. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/agglomeration.hxx +0 -0
  123. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/breadth_first_search.hxx +0 -0
  124. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/connected_components.hxx +0 -0
  125. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/detail/fusion_contract.hxx +0 -0
  126. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/edge_weighted_watershed.hxx +0 -0
  127. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/feature_accumulation.hxx +0 -0
  128. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/grid_edge_projection.hxx +0 -0
  129. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/grid_features.hxx +0 -0
  130. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/grid_graph.hxx +0 -0
  131. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/label_accumulation.hxx +0 -0
  132. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/lifted_from_affinities.hxx +0 -0
  133. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/lifted_multicut/detail.hxx +0 -0
  134. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/lifted_multicut/fusion_move.hxx +0 -0
  135. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/lifted_multicut/greedy_additive.hxx +0 -0
  136. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/lifted_multicut/kernighan_lin.hxx +0 -0
  137. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/lifted_multicut/lifted_from_node_labels.hxx +0 -0
  138. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/lifted_multicut/objective.hxx +0 -0
  139. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/lifted_multicut.hxx +0 -0
  140. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/multicut/detail.hxx +0 -0
  141. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/multicut/fusion_move.hxx +0 -0
  142. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/multicut/greedy_additive.hxx +0 -0
  143. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/multicut/greedy_fixation.hxx +0 -0
  144. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/multicut/kernighan_lin.hxx +0 -0
  145. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/multicut/objective.hxx +0 -0
  146. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/multicut.hxx +0 -0
  147. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/mutex_watershed/clustering.hxx +0 -0
  148. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/mutex_watershed/semantic.hxx +0 -0
  149. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/mutex_watershed.hxx +0 -0
  150. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/node_label_projection.hxx +0 -0
  151. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/proposal_generator.hxx +0 -0
  152. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/proposal_generators/greedy_additive_multicut.hxx +0 -0
  153. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/proposal_generators/watershed.hxx +0 -0
  154. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/rag_coordinates.hxx +0 -0
  155. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/region_adjacency_graph.hxx +0 -0
  156. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/graph/undirected_graph.hxx +0 -0
  157. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/label_multiset/downsample.hxx +0 -0
  158. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/label_multiset/from_labels.hxx +0 -0
  159. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/label_multiset/merger.hxx +0 -0
  160. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/label_multiset/multiset.hxx +0 -0
  161. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/label_multiset/read_subset.hxx +0 -0
  162. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/mesh_smoothing.hxx +0 -0
  163. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/non_maximum_distance_suppression.hxx +0 -0
  164. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/overlap.hxx +0 -0
  165. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/run_length.hxx +0 -0
  166. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/segmentation/connected_components.hxx +0 -0
  167. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/segmentation/mutex_watershed.hxx +0 -0
  168. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/segmentation/relabel_sequential.hxx +0 -0
  169. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/segmentation/semantic_mutex_watershed.hxx +0 -0
  170. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/segmentation/watershed.hxx +0 -0
  171. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/take_dict.hxx +0 -0
  172. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/include/bioimage_cpp/util/union_find.hxx +0 -0
  173. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/pyproject.toml +0 -0
  174. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bindings/affinities.cxx +0 -0
  175. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bindings/affinities.hxx +0 -0
  176. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bindings/blocking.cxx +0 -0
  177. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bindings/blocking.hxx +0 -0
  178. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bindings/distance.cxx +0 -0
  179. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bindings/distance.hxx +0 -0
  180. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bindings/filters.cxx +0 -0
  181. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bindings/filters.hxx +0 -0
  182. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bindings/flow.cxx +0 -0
  183. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bindings/flow.hxx +0 -0
  184. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bindings/graph.cxx +0 -0
  185. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bindings/graph.hxx +0 -0
  186. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bindings/ground_truth.cxx +0 -0
  187. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bindings/ground_truth.hxx +0 -0
  188. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bindings/label_multiset.cxx +0 -0
  189. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bindings/label_multiset.hxx +0 -0
  190. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bindings/module.cxx +0 -0
  191. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bindings/segmentation.cxx +0 -0
  192. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bindings/segmentation.hxx +0 -0
  193. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bindings/transformation.hxx +0 -0
  194. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bindings/util.cxx +0 -0
  195. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bindings/util.hxx +0 -0
  196. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bindings/utils.cxx +0 -0
  197. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bindings/utils.hxx +0 -0
  198. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bioimage_cpp/__init__.py +0 -0
  199. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bioimage_cpp/_data.py +0 -0
  200. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bioimage_cpp/affinities/__init__.py +0 -0
  201. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bioimage_cpp/affinities/compute_affinities.py +0 -0
  202. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bioimage_cpp/affinities/compute_embedding_distances.py +0 -0
  203. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bioimage_cpp/distance/__init__.py +0 -0
  204. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bioimage_cpp/distance/_distance.py +0 -0
  205. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bioimage_cpp/filters/__init__.py +0 -0
  206. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bioimage_cpp/filters/_filters.py +0 -0
  207. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bioimage_cpp/flow/__init__.py +0 -0
  208. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bioimage_cpp/flow/_flow.py +0 -0
  209. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bioimage_cpp/graph/__init__.py +0 -0
  210. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bioimage_cpp/graph/_external.py +0 -0
  211. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bioimage_cpp/graph/_shared.py +0 -0
  212. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bioimage_cpp/graph/agglomeration.py +0 -0
  213. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bioimage_cpp/graph/features/__init__.py +0 -0
  214. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bioimage_cpp/graph/lifted_multicut/__init__.py +0 -0
  215. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bioimage_cpp/graph/multicut/__init__.py +0 -0
  216. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bioimage_cpp/graph/mutex_watershed.py +0 -0
  217. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bioimage_cpp/label_multiset/__init__.py +0 -0
  218. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bioimage_cpp/segmentation/__init__.py +0 -0
  219. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bioimage_cpp/segmentation/label.py +0 -0
  220. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bioimage_cpp/segmentation/mutex_watershed.py +0 -0
  221. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bioimage_cpp/segmentation/relabel_sequential.py +0 -0
  222. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bioimage_cpp/segmentation/watershed.py +0 -0
  223. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/bioimage_cpp/utils.py +0 -0
  224. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/cpp/segmentation/mutex_watershed.cxx +0 -0
  225. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/cpp/segmentation/semantic_mutex_watershed.cxx +0 -0
  226. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/src/cpp/take_dict.cxx +0 -0
  227. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/affinities/test_compute_affinities.py +0 -0
  228. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/affinities/test_compute_embedding_distances.py +0 -0
  229. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/distance/test_distance_transform.py +0 -0
  230. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/distance/test_non_maximum_distance_suppression.py +0 -0
  231. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/agglomeration/__init__.py +0 -0
  232. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/agglomeration/_helpers.py +0 -0
  233. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/agglomeration/test_edge_weighted.py +0 -0
  234. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/agglomeration/test_gasp.py +0 -0
  235. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/agglomeration/test_mala.py +0 -0
  236. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/agglomeration/test_node_and_edge_weighted.py +0 -0
  237. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/lifted_multicut/__init__.py +0 -0
  238. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/lifted_multicut/_helpers.py +0 -0
  239. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/lifted_multicut/conftest.py +0 -0
  240. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/lifted_multicut/test_external_problem.py +0 -0
  241. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/lifted_multicut/test_fusion_move.py +0 -0
  242. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/lifted_multicut/test_greedy_additive.py +0 -0
  243. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/lifted_multicut/test_kernighan_lin.py +0 -0
  244. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/lifted_multicut/test_lifted_edges_from_node_labels.py +0 -0
  245. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/lifted_multicut/test_objective.py +0 -0
  246. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/multicut/__init__.py +0 -0
  247. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/multicut/_helpers.py +0 -0
  248. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/multicut/conftest.py +0 -0
  249. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/multicut/test_chain_decomposer.py +0 -0
  250. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/multicut/test_external_problem.py +0 -0
  251. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/multicut/test_fusion_move.py +0 -0
  252. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/multicut/test_greedy_additive.py +0 -0
  253. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/multicut/test_greedy_fixation.py +0 -0
  254. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/multicut/test_kernighan_lin.py +0 -0
  255. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/multicut/test_objective.py +0 -0
  256. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/multicut/test_proposal_generators.py +0 -0
  257. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/test_breadth_first_search.py +0 -0
  258. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/test_connected_components.py +0 -0
  259. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/test_edge_weighted_watershed.py +0 -0
  260. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/test_grid_affinity_multicut_integration.py +0 -0
  261. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/test_grid_features.py +0 -0
  262. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/test_grid_graph.py +0 -0
  263. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/test_mutex_watershed_graph.py +0 -0
  264. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/test_node_label_projection.py +0 -0
  265. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/test_rag_accumulate_labels.py +0 -0
  266. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/test_rag_coordinates.py +0 -0
  267. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/test_rag_features.py +0 -0
  268. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/test_rag_lifted_features.py +0 -0
  269. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/test_rag_multicut_integration.py +0 -0
  270. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/test_region_adjacency_graph.py +0 -0
  271. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/test_semantic_mutex_watershed_graph.py +0 -0
  272. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/graph/test_undirected_graph.py +0 -0
  273. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/label_multiset/__init__.py +0 -0
  274. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/label_multiset/test_against_nifty.py +0 -0
  275. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/label_multiset/test_downsample.py +0 -0
  276. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/label_multiset/test_merger.py +0 -0
  277. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/label_multiset/test_read_subset.py +0 -0
  278. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/segmentation/test_label.py +0 -0
  279. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/segmentation/test_mutex_watershed.py +0 -0
  280. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/segmentation/test_relabel_sequential.py +0 -0
  281. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/segmentation/test_semantic_mutex_watershed.py +0 -0
  282. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/segmentation/test_watershed.py +0 -0
  283. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/segmentation/test_watershed_from_affinities.py +0 -0
  284. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/test_blocking.py +0 -0
  285. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/test_filters.py +0 -0
  286. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/test_flow.py +0 -0
  287. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/test_ground_truth_overlap.py +0 -0
  288. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/test_util_union_find.py +0 -0
  289. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/test_utils_compute_rle.py +0 -0
  290. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/test_utils_mesh_smoothing.py +0 -0
  291. {bioimage_cpp-0.4.0 → bioimage_cpp-0.5.0}/tests/test_utils_take_dict.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: bioimage-cpp
3
- Version: 0.4.0
3
+ Version: 0.5.0
4
4
  Summary: Dependency-light C++ bioimage analysis algorithms with Python bindings
5
5
  Author: bioimage-cpp contributors
6
6
  License: MIT
@@ -495,6 +495,40 @@ inline double cubic_3d(
495
495
  return value;
496
496
  }
497
497
 
498
+ // Dispatch to the per-voxel sampler for the requested interpolation order. Shared by the affine and
499
+ // map_coordinates kernels so the interpolation backend lives in exactly one place. `order` must be in
500
+ // 0..5 (validated by the public entry points before the sampling loop).
501
+ template <class T>
502
+ inline double sample_2d(
503
+ const T *data, std::ptrdiff_t in_h, std::ptrdiff_t in_w,
504
+ double cy, double cx, const int order, double fill
505
+ ) {
506
+ switch (order) {
507
+ case 0: return nearest_2d(data, in_h, in_w, cy, cx, fill);
508
+ case 1: return linear_2d(data, in_h, in_w, cy, cx, fill);
509
+ case 2: return bspline_2d<2>(data, in_h, in_w, cy, cx, fill);
510
+ case 3: return cubic_2d(data, in_h, in_w, cy, cx, fill);
511
+ case 4: return bspline_2d<4>(data, in_h, in_w, cy, cx, fill);
512
+ default: return bspline_2d<5>(data, in_h, in_w, cy, cx, fill); // 5
513
+ }
514
+ }
515
+
516
+ template <class T>
517
+ inline double sample_3d(
518
+ const T *data,
519
+ std::ptrdiff_t in_d, std::ptrdiff_t in_h, std::ptrdiff_t in_w,
520
+ double cz, double cy, double cx, const int order, double fill
521
+ ) {
522
+ switch (order) {
523
+ case 0: return nearest_3d(data, in_d, in_h, in_w, cz, cy, cx, fill);
524
+ case 1: return linear_3d(data, in_d, in_h, in_w, cz, cy, cx, fill);
525
+ case 2: return bspline_3d<2>(data, in_d, in_h, in_w, cz, cy, cx, fill);
526
+ case 3: return cubic_3d(data, in_d, in_h, in_w, cz, cy, cx, fill);
527
+ case 4: return bspline_3d<4>(data, in_d, in_h, in_w, cz, cy, cx, fill);
528
+ default: return bspline_3d<5>(data, in_d, in_h, in_w, cz, cy, cx, fill); // 5
529
+ }
530
+ }
531
+
498
532
  } // namespace detail
499
533
 
500
534
  // ----- 2D entry point -------------------------------------------------------
@@ -554,27 +588,7 @@ void affine_transform_2d(
554
588
  double cy = row_y;
555
589
  double cx = row_x;
556
590
  for (std::ptrdiff_t j = 0; j < out_w; ++j) {
557
- double value;
558
- switch (order) {
559
- case 0:
560
- value = detail::nearest_2d(in_data, in_h, in_w, cy, cx, fill);
561
- break;
562
- case 1:
563
- value = detail::linear_2d(in_data, in_h, in_w, cy, cx, fill);
564
- break;
565
- case 2:
566
- value = detail::bspline_2d<2>(in_data, in_h, in_w, cy, cx, fill);
567
- break;
568
- case 3:
569
- value = detail::cubic_2d(in_data, in_h, in_w, cy, cx, fill);
570
- break;
571
- case 4:
572
- value = detail::bspline_2d<4>(in_data, in_h, in_w, cy, cx, fill);
573
- break;
574
- default: // 5
575
- value = detail::bspline_2d<5>(in_data, in_h, in_w, cy, cx, fill);
576
- break;
577
- }
591
+ const double value = detail::sample_2d(in_data, in_h, in_w, cy, cx, order, fill);
578
592
  *out_ptr++ = detail::to_output<T>(value);
579
593
  cy += m01;
580
594
  cx += m11;
@@ -655,33 +669,8 @@ void affine_transform_3d(
655
669
  double cy = row_y;
656
670
  double cx = row_x;
657
671
  for (std::ptrdiff_t j = 0; j < out_w; ++j) {
658
- double value;
659
- switch (order) {
660
- case 0:
661
- value = detail::nearest_3d(in_data, in_d, in_h, in_w,
662
- cz, cy, cx, fill);
663
- break;
664
- case 1:
665
- value = detail::linear_3d(in_data, in_d, in_h, in_w,
666
- cz, cy, cx, fill);
667
- break;
668
- case 2:
669
- value = detail::bspline_3d<2>(in_data, in_d, in_h, in_w,
670
- cz, cy, cx, fill);
671
- break;
672
- case 3:
673
- value = detail::cubic_3d(in_data, in_d, in_h, in_w,
674
- cz, cy, cx, fill);
675
- break;
676
- case 4:
677
- value = detail::bspline_3d<4>(in_data, in_d, in_h, in_w,
678
- cz, cy, cx, fill);
679
- break;
680
- default: // 5
681
- value = detail::bspline_3d<5>(in_data, in_d, in_h, in_w,
682
- cz, cy, cx, fill);
683
- break;
684
- }
672
+ const double value = detail::sample_3d(in_data, in_d, in_h, in_w,
673
+ cz, cy, cx, order, fill);
685
674
  *out_ptr++ = detail::to_output<T>(value);
686
675
  cz += m02;
687
676
  cy += m12;
@@ -0,0 +1,129 @@
1
+ #pragma once
2
+
3
+ // Coordinate-based resampling (the analogue of ``scipy.ndimage.map_coordinates``). For every output
4
+ // voxel the source coordinate to sample is read from an explicit ``coordinates`` array, instead of
5
+ // being computed from an affine matrix. The per-voxel interpolation reuses the affine samplers
6
+ // (``detail::sample_2d`` / ``detail::sample_3d``) so the interpolation backend lives in one place.
7
+ //
8
+ // This kernel is pure and in-memory (NumPy in, NumPy out); reading the source data and producing the
9
+ // coordinate (deformation) field are the caller's responsibility.
10
+
11
+ #include "bioimage_cpp/transformation/affine.hxx"
12
+
13
+ namespace bioimage_cpp::transformation {
14
+
15
+ namespace detail {
16
+
17
+ // Validate that ``coordinates`` is a ``(D, *output_shape)`` field, i.e. it carries one source
18
+ // coordinate per output voxel along its leading axis.
19
+ template <std::size_t D, class T>
20
+ void require_coordinates(const ConstArrayView<double> &coordinates, const ArrayView<T> &output) {
21
+ if (coordinates.ndim() != static_cast<std::ptrdiff_t>(D + 1)) {
22
+ throw std::invalid_argument(
23
+ "coordinates must have ndim=" + std::to_string(D + 1) +
24
+ ", got ndim=" + std::to_string(coordinates.ndim())
25
+ );
26
+ }
27
+ if (coordinates.shape[0] != static_cast<std::ptrdiff_t>(D)) {
28
+ throw std::invalid_argument(
29
+ "coordinates.shape[0] must equal the data dimension " + std::to_string(D) +
30
+ ", got " + std::to_string(coordinates.shape[0])
31
+ );
32
+ }
33
+ for (std::size_t axis = 0; axis < D; ++axis) {
34
+ if (coordinates.shape[axis + 1] != output.shape[axis]) {
35
+ throw std::invalid_argument(
36
+ "coordinates spatial shape (coordinates.shape[1:]) must match the output shape"
37
+ );
38
+ }
39
+ }
40
+ }
41
+
42
+ } // namespace detail
43
+
44
+ // ----- 2D entry point -------------------------------------------------------
45
+
46
+ template <class T>
47
+ void map_coordinates_2d(
48
+ const ConstArrayView<T> &input,
49
+ ArrayView<T> &output,
50
+ const ConstArrayView<double> &coordinates,
51
+ const int order,
52
+ const T fill_value
53
+ ) {
54
+ detail::require_views<2, T>(input, output);
55
+ detail::require_coordinates<2, T>(coordinates, output);
56
+ if (order < 0 || order > 5) {
57
+ throw std::invalid_argument(
58
+ "order must be in 0..5, got " + std::to_string(order)
59
+ );
60
+ }
61
+
62
+ const auto out_h = output.shape[0];
63
+ const auto out_w = output.shape[1];
64
+ if (out_h == 0 || out_w == 0) return;
65
+
66
+ const auto in_h = input.shape[0];
67
+ const auto in_w = input.shape[1];
68
+
69
+ // coordinates is C-contiguous with shape (2, out_h, out_w), so axis-d coordinates form a
70
+ // contiguous block of n_out doubles starting at d * n_out.
71
+ const std::ptrdiff_t n_out = out_h * out_w;
72
+ const double *cy = coordinates.data;
73
+ const double *cx = coordinates.data + n_out;
74
+
75
+ const double fill = static_cast<double>(fill_value);
76
+ const T *in_data = input.data;
77
+ T *out_ptr = output.data;
78
+
79
+ for (std::ptrdiff_t p = 0; p < n_out; ++p) {
80
+ const double value = detail::sample_2d(in_data, in_h, in_w, cy[p], cx[p], order, fill);
81
+ out_ptr[p] = detail::to_output<T>(value);
82
+ }
83
+ }
84
+
85
+ // ----- 3D entry point -------------------------------------------------------
86
+
87
+ template <class T>
88
+ void map_coordinates_3d(
89
+ const ConstArrayView<T> &input,
90
+ ArrayView<T> &output,
91
+ const ConstArrayView<double> &coordinates,
92
+ const int order,
93
+ const T fill_value
94
+ ) {
95
+ detail::require_views<3, T>(input, output);
96
+ detail::require_coordinates<3, T>(coordinates, output);
97
+ if (order < 0 || order > 5) {
98
+ throw std::invalid_argument(
99
+ "order must be in 0..5, got " + std::to_string(order)
100
+ );
101
+ }
102
+
103
+ const auto out_d = output.shape[0];
104
+ const auto out_h = output.shape[1];
105
+ const auto out_w = output.shape[2];
106
+ if (out_d == 0 || out_h == 0 || out_w == 0) return;
107
+
108
+ const auto in_d = input.shape[0];
109
+ const auto in_h = input.shape[1];
110
+ const auto in_w = input.shape[2];
111
+
112
+ // coordinates is C-contiguous with shape (3, out_d, out_h, out_w).
113
+ const std::ptrdiff_t n_out = out_d * out_h * out_w;
114
+ const double *cz = coordinates.data;
115
+ const double *cy = coordinates.data + n_out;
116
+ const double *cx = coordinates.data + 2 * n_out;
117
+
118
+ const double fill = static_cast<double>(fill_value);
119
+ const T *in_data = input.data;
120
+ T *out_ptr = output.data;
121
+
122
+ for (std::ptrdiff_t p = 0; p < n_out; ++p) {
123
+ const double value = detail::sample_3d(in_data, in_d, in_h, in_w,
124
+ cz[p], cy[p], cx[p], order, fill);
125
+ out_ptr[p] = detail::to_output<T>(value);
126
+ }
127
+ }
128
+
129
+ } // namespace bioimage_cpp::transformation
@@ -3,6 +3,7 @@
3
3
  #include "bioimage_cpp/array_view.hxx"
4
4
  #include "bioimage_cpp/detail/grid.hxx"
5
5
  #include "bioimage_cpp/transformation/affine.hxx"
6
+ #include "bioimage_cpp/transformation/coordinate.hxx"
6
7
 
7
8
  #include <nanobind/ndarray.h>
8
9
 
@@ -113,6 +114,86 @@ void bind_affine_for_dtype(nb::module_ &m, const char *name_2d, const char *name
113
114
  );
114
115
  }
115
116
 
117
+ template <std::size_t D, class T>
118
+ OutputArray<T> map_coordinates_t(
119
+ ConstArray<T> input,
120
+ MatrixArray coordinates,
121
+ OutputArray<T> output,
122
+ const int order,
123
+ const T fill_value
124
+ ) {
125
+ if (input.ndim() != D) {
126
+ throw std::invalid_argument(
127
+ "input must have ndim=" + std::to_string(D) +
128
+ ", got ndim=" + std::to_string(input.ndim())
129
+ );
130
+ }
131
+ if (output.ndim() != D) {
132
+ throw std::invalid_argument(
133
+ "output must have ndim=" + std::to_string(D) +
134
+ ", got ndim=" + std::to_string(output.ndim())
135
+ );
136
+ }
137
+ if (coordinates.ndim() != D + 1) {
138
+ throw std::invalid_argument(
139
+ "coordinates must have ndim=" + std::to_string(D + 1) +
140
+ ", got ndim=" + std::to_string(coordinates.ndim())
141
+ );
142
+ }
143
+
144
+ const auto input_shape = shape_of(input);
145
+ const auto input_strides = detail::c_order_strides(input_shape);
146
+ const auto coordinates_shape = shape_of(coordinates);
147
+ const auto coordinates_strides = detail::c_order_strides(coordinates_shape);
148
+ const auto output_shape = shape_of(output);
149
+ const auto output_strides = detail::c_order_strides(output_shape);
150
+
151
+ ConstArrayView<T> input_view{input.data(), input_shape, input_strides};
152
+ ArrayView<T> output_view{output.data(), output_shape, output_strides};
153
+ ConstArrayView<double> coordinates_view{
154
+ coordinates.data(), coordinates_shape, coordinates_strides
155
+ };
156
+
157
+ {
158
+ nb::gil_scoped_release release;
159
+ if constexpr (D == 2) {
160
+ transformation::map_coordinates_2d<T>(
161
+ input_view, output_view, coordinates_view, order, fill_value
162
+ );
163
+ } else {
164
+ transformation::map_coordinates_3d<T>(
165
+ input_view, output_view, coordinates_view, order, fill_value
166
+ );
167
+ }
168
+ }
169
+
170
+ return output;
171
+ }
172
+
173
+ template <class T>
174
+ void bind_map_coordinates_for_dtype(nb::module_ &m, const char *name_2d, const char *name_3d) {
175
+ m.def(
176
+ name_2d,
177
+ &map_coordinates_t<2, T>,
178
+ nb::arg("input"),
179
+ nb::arg("coordinates"),
180
+ nb::arg("output"),
181
+ nb::arg("order"),
182
+ nb::arg("fill_value"),
183
+ "Apply a 2D coordinate-based resampling into a pre-allocated NumPy array."
184
+ );
185
+ m.def(
186
+ name_3d,
187
+ &map_coordinates_t<3, T>,
188
+ nb::arg("input"),
189
+ nb::arg("coordinates"),
190
+ nb::arg("output"),
191
+ nb::arg("order"),
192
+ nb::arg("fill_value"),
193
+ "Apply a 3D coordinate-based resampling into a pre-allocated NumPy array."
194
+ );
195
+ }
196
+
116
197
  } // namespace
117
198
 
118
199
  void bind_transformation(nb::module_ &m) {
@@ -146,6 +227,37 @@ void bind_transformation(nb::module_ &m) {
146
227
  bind_affine_for_dtype<double>(
147
228
  m, "_affine_transform_2d_float64", "_affine_transform_3d_float64"
148
229
  );
230
+
231
+ bind_map_coordinates_for_dtype<std::uint8_t>(
232
+ m, "_map_coordinates_2d_uint8", "_map_coordinates_3d_uint8"
233
+ );
234
+ bind_map_coordinates_for_dtype<std::uint16_t>(
235
+ m, "_map_coordinates_2d_uint16", "_map_coordinates_3d_uint16"
236
+ );
237
+ bind_map_coordinates_for_dtype<std::uint32_t>(
238
+ m, "_map_coordinates_2d_uint32", "_map_coordinates_3d_uint32"
239
+ );
240
+ bind_map_coordinates_for_dtype<std::uint64_t>(
241
+ m, "_map_coordinates_2d_uint64", "_map_coordinates_3d_uint64"
242
+ );
243
+ bind_map_coordinates_for_dtype<std::int8_t>(
244
+ m, "_map_coordinates_2d_int8", "_map_coordinates_3d_int8"
245
+ );
246
+ bind_map_coordinates_for_dtype<std::int16_t>(
247
+ m, "_map_coordinates_2d_int16", "_map_coordinates_3d_int16"
248
+ );
249
+ bind_map_coordinates_for_dtype<std::int32_t>(
250
+ m, "_map_coordinates_2d_int32", "_map_coordinates_3d_int32"
251
+ );
252
+ bind_map_coordinates_for_dtype<std::int64_t>(
253
+ m, "_map_coordinates_2d_int64", "_map_coordinates_3d_int64"
254
+ );
255
+ bind_map_coordinates_for_dtype<float>(
256
+ m, "_map_coordinates_2d_float32", "_map_coordinates_3d_float32"
257
+ );
258
+ bind_map_coordinates_for_dtype<double>(
259
+ m, "_map_coordinates_2d_float64", "_map_coordinates_3d_float64"
260
+ );
149
261
  }
150
262
 
151
263
  } // namespace bioimage_cpp::bindings
@@ -0,0 +1 @@
1
+ __version__ = "0.5.0"
@@ -3,11 +3,13 @@
3
3
  from ._transformation import (
4
4
  affine_transform,
5
5
  compute_anti_aliasing_sigma,
6
+ map_coordinates,
6
7
  resample,
7
8
  )
8
9
 
9
10
  __all__ = [
10
11
  "affine_transform",
11
12
  "compute_anti_aliasing_sigma",
13
+ "map_coordinates",
12
14
  "resample",
13
15
  ]
@@ -36,6 +36,32 @@ _AFFINE_3D_BY_DTYPE = {
36
36
  np.dtype("float64"): _core._affine_transform_3d_float64,
37
37
  }
38
38
 
39
+ _MAP_COORDINATES_2D_BY_DTYPE = {
40
+ np.dtype("uint8"): _core._map_coordinates_2d_uint8,
41
+ np.dtype("uint16"): _core._map_coordinates_2d_uint16,
42
+ np.dtype("uint32"): _core._map_coordinates_2d_uint32,
43
+ np.dtype("uint64"): _core._map_coordinates_2d_uint64,
44
+ np.dtype("int8"): _core._map_coordinates_2d_int8,
45
+ np.dtype("int16"): _core._map_coordinates_2d_int16,
46
+ np.dtype("int32"): _core._map_coordinates_2d_int32,
47
+ np.dtype("int64"): _core._map_coordinates_2d_int64,
48
+ np.dtype("float32"): _core._map_coordinates_2d_float32,
49
+ np.dtype("float64"): _core._map_coordinates_2d_float64,
50
+ }
51
+
52
+ _MAP_COORDINATES_3D_BY_DTYPE = {
53
+ np.dtype("uint8"): _core._map_coordinates_3d_uint8,
54
+ np.dtype("uint16"): _core._map_coordinates_3d_uint16,
55
+ np.dtype("uint32"): _core._map_coordinates_3d_uint32,
56
+ np.dtype("uint64"): _core._map_coordinates_3d_uint64,
57
+ np.dtype("int8"): _core._map_coordinates_3d_int8,
58
+ np.dtype("int16"): _core._map_coordinates_3d_int16,
59
+ np.dtype("int32"): _core._map_coordinates_3d_int32,
60
+ np.dtype("int64"): _core._map_coordinates_3d_int64,
61
+ np.dtype("float32"): _core._map_coordinates_3d_float32,
62
+ np.dtype("float64"): _core._map_coordinates_3d_float64,
63
+ }
64
+
39
65
 
40
66
  def _normalize_matrix(matrix, ndim: int) -> np.ndarray:
41
67
  array = np.asarray(matrix, dtype=np.float64)
@@ -340,3 +366,83 @@ def affine_transform(
340
366
  output = _validate_or_allocate_out(out, output_shape, dtype)
341
367
  run(contiguous, normalized_matrix, starts, output, order, typed_fill)
342
368
  return output
369
+
370
+
371
+ def _normalize_coordinates(coordinates, ndim: int) -> tuple[np.ndarray, tuple[int, ...]]:
372
+ array = np.ascontiguousarray(coordinates, dtype=np.float64)
373
+ if array.ndim != ndim + 1:
374
+ raise ValueError(
375
+ f"coordinates must have ndim={ndim + 1} (a leading axis of length {ndim} plus the "
376
+ f"output shape), got ndim={array.ndim}"
377
+ )
378
+ if array.shape[0] != ndim:
379
+ raise ValueError(
380
+ f"coordinates.shape[0] must equal the data dimension {ndim}, got {array.shape[0]}"
381
+ )
382
+ output_shape = tuple(int(s) for s in array.shape[1:])
383
+ return array, output_shape
384
+
385
+
386
+ def map_coordinates(
387
+ data: np.ndarray,
388
+ coordinates,
389
+ *,
390
+ order: int = 1,
391
+ fill_value: Number = 0,
392
+ out: np.ndarray | None = None,
393
+ ) -> np.ndarray:
394
+ """Resample a 2D or 3D array at explicit, per-output-voxel source coordinates.
395
+
396
+ Like ``scipy.ndimage.map_coordinates``, but specialized to a same-rank resampling: for each
397
+ output voxel the source coordinate to sample is read from ``coordinates`` and the input is
398
+ interpolated there. ``coordinates`` has shape ``(ndim, *output_shape)`` in NumPy axis order, so
399
+ ``coordinates[d]`` holds the axis-``d`` source coordinate of every output voxel. The output has
400
+ the same number of dimensions as ``data`` (a 2D or 3D resampling), so ``output_shape`` =
401
+ ``coordinates.shape[1:]`` has ``ndim`` entries. This is the deformation-field counterpart of
402
+ :func:`affine_transform` (which derives the same per-voxel source coordinate from an affine
403
+ matrix) and shares its interpolation backend.
404
+
405
+ Supported interpolation orders match :func:`affine_transform`:
406
+
407
+ - ``0`` — nearest neighbour.
408
+ - ``1`` — linear (bi-/tri-linear).
409
+ - ``2`` — quadratic B-spline (3 taps per axis).
410
+ - ``3`` — local Keys cubic convolution (4 taps; Catmull-Rom, ``a=-0.5``); reproduces input
411
+ exactly at integer coordinates.
412
+ - ``4`` — quartic B-spline (5 taps per axis).
413
+ - ``5`` — quintic B-spline (6 taps per axis).
414
+
415
+ Orders ``2``, ``4``, ``5`` evaluate the cardinal B-spline kernel directly on the input samples
416
+ (no prefilter); they are low-pass smoothing, not interpolating. See :func:`affine_transform`
417
+ for the full discussion.
418
+
419
+ The output preserves the input dtype; integer outputs round to nearest and clamp to the dtype
420
+ range. Coordinates that map outside the input contribute ``fill_value``.
421
+
422
+ Pass a pre-allocated, C-contiguous, writable NumPy array as ``out`` to write the result in
423
+ place; it must have shape ``coordinates.shape[1:]`` and dtype equal to ``data.dtype``.
424
+ """
425
+ array = np.asarray(data)
426
+ if array.ndim not in (2, 3):
427
+ raise ValueError(f"data must be 2D or 3D, got ndim={array.ndim}")
428
+
429
+ order = int(order)
430
+ if order not in (0, 1, 2, 3, 4, 5):
431
+ raise ValueError(f"order must be in 0..5, got {order}")
432
+
433
+ table = _MAP_COORDINATES_2D_BY_DTYPE if array.ndim == 2 else _MAP_COORDINATES_3D_BY_DTYPE
434
+ dtype = array.dtype
435
+ try:
436
+ run = table[dtype]
437
+ except KeyError as error:
438
+ supported = ", ".join(str(name) for name in table)
439
+ raise TypeError(
440
+ f"data must have one of dtypes ({supported}), got dtype={dtype}"
441
+ ) from error
442
+
443
+ coords, output_shape = _normalize_coordinates(coordinates, array.ndim)
444
+ contiguous = np.ascontiguousarray(array)
445
+ typed_fill = _normalize_fill_value(fill_value, dtype)
446
+ output = _validate_or_allocate_out(out, output_shape, dtype)
447
+ run(contiguous, coords, output, order, typed_fill)
448
+ return output
@@ -408,3 +408,124 @@ def test_invalid_inputs_raise():
408
408
  bic.transformation.affine_transform(data, _matrix(2), bounding_box=(slice(None, None, 2), slice(None)))
409
409
  with pytest.raises(TypeError, match="dtype"):
410
410
  bic.transformation.affine_transform(np.zeros((4, 4), dtype=np.bool_), _matrix(2))
411
+
412
+
413
+ # ---------------------------------------------------------------------------
414
+ # map_coordinates
415
+ # ---------------------------------------------------------------------------
416
+
417
+ _ALL_DTYPES = [
418
+ np.uint8, np.uint16, np.uint32, np.uint64,
419
+ np.int8, np.int16, np.int32, np.int64,
420
+ np.float32, np.float64,
421
+ ]
422
+
423
+
424
+ def _affine_coords(matrix, shape):
425
+ """The (ndim, *shape) coordinate field that reproduces `matrix` as an explicit deformation."""
426
+ ndim = len(shape)
427
+ grid = np.indices(shape, dtype=np.float64)
428
+ coords = np.empty_like(grid)
429
+ for d in range(ndim):
430
+ acc = np.full(shape, matrix[d, ndim], dtype=np.float64)
431
+ for k in range(ndim):
432
+ acc = acc + matrix[d, k] * grid[k]
433
+ coords[d] = acc
434
+ return coords
435
+
436
+
437
+ @pytest.mark.parametrize("order", [0, 1, 2, 3, 4, 5])
438
+ @pytest.mark.parametrize("dtype", _ALL_DTYPES)
439
+ def test_map_coordinates_matches_affine_2d(order, dtype):
440
+ # A coordinate field built from an affine matrix must reproduce affine_transform exactly: same
441
+ # interpolation backend, so the results are bit-identical for every order and dtype.
442
+ data = (np.arange(5 * 7) % 17).astype(dtype).reshape(5, 7)
443
+ matrix = _matrix(2, translation=[0.5, -1.25])
444
+ coords = _affine_coords(matrix, data.shape)
445
+ got = bic.transformation.map_coordinates(data, coords, order=order, fill_value=0)
446
+ ref = bic.transformation.affine_transform(data, matrix, order=order, fill_value=0)
447
+ np.testing.assert_array_equal(got, ref)
448
+
449
+
450
+ @pytest.mark.parametrize("order", [0, 1, 2, 3, 4, 5])
451
+ @pytest.mark.parametrize("dtype", [np.uint8, np.uint16, np.int32, np.float32, np.float64])
452
+ def test_map_coordinates_matches_affine_3d(order, dtype):
453
+ data = (np.arange(4 * 5 * 6) % 13).astype(dtype).reshape(4, 5, 6)
454
+ matrix = _matrix(3, translation=[0.25, -0.5, 1.0])
455
+ coords = _affine_coords(matrix, data.shape)
456
+ got = bic.transformation.map_coordinates(data, coords, order=order, fill_value=0)
457
+ ref = bic.transformation.affine_transform(data, matrix, order=order, fill_value=0)
458
+ np.testing.assert_array_equal(got, ref)
459
+
460
+
461
+ @pytest.mark.parametrize("order", [0, 1])
462
+ @pytest.mark.parametrize("ndim", [2, 3])
463
+ def test_map_coordinates_matches_scipy(order, ndim):
464
+ sp = pytest.importorskip("scipy.ndimage")
465
+ rng = np.random.default_rng(0)
466
+ shape = (9, 11) if ndim == 2 else (6, 7, 8)
467
+ data = rng.random(shape).astype(np.float64)
468
+ # random source coordinates strictly inside the volume, so boundary handling is not involved.
469
+ coords = np.stack([rng.uniform(1.0, s - 2.0, size=shape) for s in shape])
470
+ got = bic.transformation.map_coordinates(data, coords, order=order)
471
+ ref = sp.map_coordinates(data, coords, order=order, mode="nearest", prefilter=False)
472
+ np.testing.assert_allclose(got, ref, atol=1e-6)
473
+
474
+
475
+ @pytest.mark.parametrize("order", [0, 1, 3])
476
+ @pytest.mark.parametrize("shape", [(5, 7), (4, 5, 6)])
477
+ def test_map_coordinates_identity_round_trip(order, shape):
478
+ # Sampling at the integer grid reproduces the input exactly for the interpolating orders.
479
+ data = np.arange(int(np.prod(shape)), dtype=np.float32).reshape(shape)
480
+ coords = np.indices(shape, dtype=np.float64)
481
+ got = bic.transformation.map_coordinates(data, coords, order=order, fill_value=-1)
482
+ np.testing.assert_array_equal(got, data)
483
+
484
+
485
+ @pytest.mark.parametrize("order", [0, 1, 3])
486
+ def test_map_coordinates_out_of_bounds_uses_fill(order):
487
+ data = np.arange(16, dtype=np.float32).reshape(4, 4)
488
+ coords = np.full((2, 3, 3), -50.0) # every output voxel maps far outside the input
489
+ got = bic.transformation.map_coordinates(data, coords, order=order, fill_value=7.0)
490
+ np.testing.assert_array_equal(got, np.full((3, 3), 7.0, dtype=np.float32))
491
+
492
+
493
+ def test_map_coordinates_writes_into_out():
494
+ data = np.arange(20, dtype=np.float64).reshape(4, 5)
495
+ coords = np.indices(data.shape, dtype=np.float64)
496
+ out = np.empty(data.shape, dtype=np.float64)
497
+ returned = bic.transformation.map_coordinates(data, coords, order=1, out=out)
498
+ assert returned is out
499
+ np.testing.assert_array_equal(out, data)
500
+
501
+
502
+ def test_map_coordinates_accepts_noncontiguous_coordinates():
503
+ data = np.arange(20, dtype=np.float64).reshape(4, 5)
504
+ matrix = _matrix(2, translation=[0.5, 0.5])
505
+ coords = _affine_coords(matrix, data.shape)
506
+ noncontig = np.asfortranarray(coords) # coerced to contiguous float64 internally
507
+ assert not noncontig.flags.c_contiguous
508
+ got = bic.transformation.map_coordinates(data, noncontig, order=1)
509
+ ref = bic.transformation.affine_transform(data, matrix, order=1)
510
+ np.testing.assert_array_equal(got, ref)
511
+
512
+
513
+ def test_map_coordinates_invalid_inputs_raise():
514
+ data = np.zeros((4, 5), dtype=np.float32)
515
+ good = np.indices(data.shape).astype(np.float64)
516
+ with pytest.raises(ValueError, match="2D or 3D"):
517
+ bic.transformation.map_coordinates(np.zeros((4,), dtype=np.float32), np.zeros((1, 4)))
518
+ with pytest.raises(ValueError, match="order"):
519
+ bic.transformation.map_coordinates(data, good, order=6)
520
+ # coordinates must have ndim == data.ndim + 1
521
+ with pytest.raises(ValueError, match="ndim"):
522
+ bic.transformation.map_coordinates(data, np.zeros((2, 4), dtype=np.float64))
523
+ # coordinates leading axis must equal data ndim
524
+ with pytest.raises(ValueError, match=r"shape\[0\]"):
525
+ bic.transformation.map_coordinates(data, np.zeros((3, 4, 5), dtype=np.float64))
526
+ with pytest.raises(TypeError, match="dtype"):
527
+ bic.transformation.map_coordinates(np.zeros((4, 5), dtype=np.bool_), good)
528
+ with pytest.raises(ValueError, match="shape"):
529
+ bic.transformation.map_coordinates(data, good, out=np.empty((3, 3), dtype=np.float32))
530
+ with pytest.raises(TypeError, match="dtype"):
531
+ bic.transformation.map_coordinates(data, good, out=np.empty((4, 5), dtype=np.float64))
@@ -1 +0,0 @@
1
- __version__ = "0.4.0"
File without changes
File without changes
File without changes
File without changes