arraybridge 0.3.7__tar.gz → 0.3.8__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.
- {arraybridge-0.3.7 → arraybridge-0.3.8}/PKG-INFO +1 -1
- {arraybridge-0.3.7 → arraybridge-0.3.8}/src/arraybridge/__init__.py +1 -1
- {arraybridge-0.3.7 → arraybridge-0.3.8}/src/arraybridge/array_operations.py +44 -2
- {arraybridge-0.3.7 → arraybridge-0.3.8}/src/arraybridge/types.py +14 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/tests/test_native_geometry.py +15 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/.github/workflows/ci.yml +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/.github/workflows/coverage-pages.yml +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/.github/workflows/gpu-tests.yml +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/.github/workflows/publish.yml +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/.gitignore +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/.readthedocs.yml +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/ADDING_NEW_FRAMEWORKS.md +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/CONTRIBUTING.md +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/LICENSE +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/README.md +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/TESTING.md +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/docs/Makefile +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/docs/archive/CI_ARTIFACT_UPDATE.md +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/docs/archive/CI_CUPY_FIX.md +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/docs/archive/CI_IMPROVEMENTS.md +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/docs/archive/CONFLICT_VISUALIZATION.md +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/docs/archive/COVERAGE_AUDIT_PLAN.md +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/docs/archive/DEPLOYMENT_SUMMARY.md +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/docs/archive/GPU_TESTING_SETUP.md +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/docs/archive/MERGE_CONFLICT_RESOLUTION.md +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/docs/archive/MIGRATION_SUMMARY.md +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/docs/archive/QUICK_FIX_GUIDE.txt +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/docs/archive/README.md +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/docs/archive/RESOLVED_FILES.md +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/docs/ci-cd.md +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/docs/source/.gitignore +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/docs/source/Makefile +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/docs/source/README.md +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/docs/source/advanced_topics.rst +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/docs/source/api_reference.rst +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/docs/source/ci-cd.rst +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/docs/source/conf.py +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/docs/source/contributing.rst +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/docs/source/converters.rst +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/docs/source/decorators.rst +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/docs/source/examples/basic_conversion.rst +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/docs/source/examples/decorators.rst +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/docs/source/examples/index.rst +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/docs/source/examples/multi_framework.rst +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/docs/source/gpu_features.rst +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/docs/source/index.rst +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/docs/source/installation.rst +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/docs/source/quickstart.rst +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/docs/source/release_035_validation.rst +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/docs/source/release_036_validation.rst +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/docs/source/stack_utils.rst +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/docs/source/user_guide.rst +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/paper.bib +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/paper.md +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/pyproject.toml +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/scripts/release.py +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/scripts/update_version.py +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/scripts/verify_release_ready.py +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/src/arraybridge/array_geometry.py +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/src/arraybridge/array_payload.py +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/src/arraybridge/converters.py +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/src/arraybridge/converters_registry.py +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/src/arraybridge/decorators.py +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/src/arraybridge/dtype_scaling.py +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/src/arraybridge/exceptions.py +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/src/arraybridge/framework_config.py +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/src/arraybridge/framework_ops.py +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/src/arraybridge/gpu_cleanup.py +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/src/arraybridge/oom_recovery.py +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/src/arraybridge/slice_processing.py +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/src/arraybridge/stack_utils.py +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/src/arraybridge/utils.py +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/tests/__init__.py +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/tests/conftest.py +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/tests/test_array_geometry.py +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/tests/test_callable_dtype_default.py +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/tests/test_converters.py +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/tests/test_converters_registry.py +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/tests/test_decorators.py +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/tests/test_dtype_scaling.py +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/tests/test_durable_decorator_context.py +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/tests/test_exceptions.py +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/tests/test_framework_config.py +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/tests/test_gpu_cleanup.py +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/tests/test_integration.py +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/tests/test_oom_recovery.py +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/tests/test_registry_integration.py +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/tests/test_slice_processing.py +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/tests/test_stack_utils.py +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/tests/test_types.py +0 -0
- {arraybridge-0.3.7 → arraybridge-0.3.8}/tests/test_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: arraybridge
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.8
|
|
4
4
|
Summary: Unified API for NumPy, CuPy, PyTorch, TensorFlow, JAX, and pyclesperanto with automatic memory type conversion
|
|
5
5
|
Project-URL: Homepage, https://github.com/OpenHCSDev/arraybridge
|
|
6
6
|
Project-URL: Documentation, https://arraybridge.readthedocs.io
|
|
@@ -114,8 +114,50 @@ class ArrayOperations(ABC):
|
|
|
114
114
|
def ones_like(reference: Any, shape: tuple[int, ...], dtype: Any, module: Any) -> Any:
|
|
115
115
|
return module.ones(shape, dtype=dtype)
|
|
116
116
|
|
|
117
|
+
@classmethod
|
|
118
|
+
def normalize_planes(
|
|
119
|
+
cls,
|
|
120
|
+
data: Any,
|
|
121
|
+
dtype: Any,
|
|
122
|
+
scales: Sequence[float | None],
|
|
123
|
+
module: Any,
|
|
124
|
+
) -> Any:
|
|
125
|
+
"""Cast and scale each plane before assembling its owned output."""
|
|
126
|
+
return cls.stack(
|
|
127
|
+
tuple(
|
|
128
|
+
(
|
|
129
|
+
cls.cast(plane, dtype, module)
|
|
130
|
+
if scale is None
|
|
131
|
+
else cls.cast(plane, dtype, module) / float(scale)
|
|
132
|
+
)
|
|
133
|
+
for plane, scale in zip(data, scales, strict=True)
|
|
134
|
+
),
|
|
135
|
+
module,
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
class MutableArrayOperations(ArrayOperations):
|
|
140
|
+
"""Arrays whose allocated output supports native in-place arithmetic."""
|
|
141
|
+
|
|
142
|
+
@classmethod
|
|
143
|
+
def normalize_planes(
|
|
144
|
+
cls,
|
|
145
|
+
data: Any,
|
|
146
|
+
dtype: Any,
|
|
147
|
+
scales: Sequence[float | None],
|
|
148
|
+
module: Any,
|
|
149
|
+
) -> Any:
|
|
150
|
+
# Integer division promotes the output dtype in the original recipe.
|
|
151
|
+
if not np.issubdtype(np.dtype(dtype), np.inexact) or len(data) == 0:
|
|
152
|
+
return super().normalize_planes(data, dtype, scales, module)
|
|
153
|
+
normalized = module.array(data, dtype=dtype, copy=True)
|
|
154
|
+
for index, scale in enumerate(scales):
|
|
155
|
+
if scale is not None:
|
|
156
|
+
normalized[index] /= float(scale)
|
|
157
|
+
return normalized
|
|
158
|
+
|
|
117
159
|
|
|
118
|
-
class NumpyArrayOperations(
|
|
160
|
+
class NumpyArrayOperations(MutableArrayOperations):
|
|
119
161
|
"""Numpy native operation leaves."""
|
|
120
162
|
|
|
121
163
|
@staticmethod
|
|
@@ -148,7 +190,7 @@ class NumpyArrayOperations(ArrayOperations):
|
|
|
148
190
|
return scaled.astype(target_dtype)
|
|
149
191
|
|
|
150
192
|
|
|
151
|
-
class CupyArrayOperations(
|
|
193
|
+
class CupyArrayOperations(MutableArrayOperations):
|
|
152
194
|
"""Cupy native operation leaves."""
|
|
153
195
|
|
|
154
196
|
@staticmethod
|
|
@@ -804,6 +804,20 @@ class MemoryType(_MemoryTypeFields, Enum):
|
|
|
804
804
|
with self.device_scope(device_id, framework):
|
|
805
805
|
return self._operations.stack(arrays, framework)
|
|
806
806
|
|
|
807
|
+
def normalize_planes(
|
|
808
|
+
self,
|
|
809
|
+
data: Any,
|
|
810
|
+
dtype: Any,
|
|
811
|
+
scales: Sequence[float | None],
|
|
812
|
+
module: Any | None = None,
|
|
813
|
+
) -> Any:
|
|
814
|
+
"""Normalize one owned plane stack through its native operation owner."""
|
|
815
|
+
if len(scales) != len(data):
|
|
816
|
+
raise ValueError("Normalization scales must match the leading plane axis.")
|
|
817
|
+
framework = module if module is not None else self.import_module()
|
|
818
|
+
with self._array_device_scope(data, framework):
|
|
819
|
+
return self._operations.normalize_planes(data, dtype, scales, framework)
|
|
820
|
+
|
|
807
821
|
def scale_dtype(
|
|
808
822
|
self,
|
|
809
823
|
data: Any,
|
|
@@ -63,3 +63,18 @@ def test_pycles_geometry_rejects_host_fallback():
|
|
|
63
63
|
PYCLESPERANTO_OPERATIONS.broadcast_to(source, (4, 2, 3), None)
|
|
64
64
|
with pytest.raises(NotImplementedError, match="dtype"):
|
|
65
65
|
PYCLESPERANTO_OPERATIONS.ones_like(source, (2, 3), bool, None)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
@pytest.mark.parametrize("dtype", (np.float32, np.complex64, np.int32))
|
|
69
|
+
def test_normalize_planes_preserves_source_and_division_dtype(dtype):
|
|
70
|
+
source = np.arange(24, dtype=dtype).reshape(2, 3, 4)[:, :, ::-1]
|
|
71
|
+
original = source.copy()
|
|
72
|
+
expected = np.stack((source[0] / 3.0, source[1]))
|
|
73
|
+
actual = MemoryType.NUMPY.normalize_planes(source, dtype, (3.0, None))
|
|
74
|
+
np.testing.assert_array_equal(actual, expected)
|
|
75
|
+
np.testing.assert_array_equal(source, original)
|
|
76
|
+
assert actual.dtype == expected.dtype
|
|
77
|
+
assert not np.shares_memory(actual, source)
|
|
78
|
+
for scales in ((3.0,), (3.0, None, 2.0)):
|
|
79
|
+
with pytest.raises(ValueError, match="leading plane axis"):
|
|
80
|
+
MemoryType.NUMPY.normalize_planes(source, dtype, scales)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|