Coverage for openhcs/processing/backends/lib_registry/pyclesperanto_registry.py: 49.3%
55 statements
« prev ^ index » next coverage.py v7.10.3, created at 2025-08-14 05:57 +0000
« prev ^ index » next coverage.py v7.10.3, created at 2025-08-14 05:57 +0000
1"""
2Clean Pyclesperanto Registry Implementation
4Implements clean abstraction with internal library-specific logic.
5All pyclesperanto-specific details (dtype conversions, Z-parameters, etc.)
6are handled internally without leaking into the ABC.
7"""
8from __future__ import annotations
10import inspect
11import numpy as np
12from functools import wraps
13from typing import Tuple, Callable, List, Any, Dict
14from openhcs.constants import MemoryType
15from openhcs.core.utils import optional_import
16from .unified_registry import LibraryRegistryBase, ProcessingContract, FunctionMetadata
18cle = optional_import("pyclesperanto")
21class PyclesperantoRegistry(LibraryRegistryBase):
22 """Clean pyclesperanto registry with internal library-specific logic."""
24 # Library-specific exclusions extending common ones
25 EXCLUSIONS = LibraryRegistryBase.COMMON_EXCLUSIONS | {
26 'push_zyx', 'pull_zyx', 'create_zyx', 'set_wait_for_kernel_finish',
27 'get_device', 'select_device', 'list_available_devices'
28 }
30 # Modules to scan for functions
31 MODULES_TO_SCAN = [""] # Pyclesperanto functions are in main namespace
33 # Memory type for this registry
34 MEMORY_TYPE = MemoryType.PYCLESPERANTO.value
36 # Float dtype for this registry
37 FLOAT_DTYPE = np.float32
39 def __init__(self):
40 super().__init__("pyclesperanto")
41 # Internal constants for dtype handling
42 self._BINARY_FUNCTIONS = {'binary_infsup', 'binary_supinf'}
43 self._UINT8_FUNCTIONS = {'mode', 'mode_box', 'mode_sphere'}
44 self._IMAGE_PARAM_NAMES = {"src", "source", "image", "input", "src1", "input_image", "input_image0"}
46 # ===== ESSENTIAL ABC METHODS =====
47 def get_library_version(self) -> str:
48 return cle.__version__
50 def is_library_available(self) -> bool:
51 return cle is not None
53 def get_library_object(self):
54 return cle
56 # ===== HOOK IMPLEMENTATIONS =====
57 def _create_array(self, shape: Tuple[int, ...], dtype):
58 return np.random.rand(*shape).astype(dtype)
60 def _check_first_parameter(self, first_param, func_name: str) -> bool:
61 return (first_param.name.lower() in self._IMAGE_PARAM_NAMES and
62 first_param.kind in (inspect.Parameter.POSITIONAL_ONLY,
63 inspect.Parameter.POSITIONAL_OR_KEYWORD))
65 def _preprocess_input(self, image, func_name: str):
66 return self._convert_input_dtype(image, func_name)
68 def _postprocess_output(self, result, original_image, func_name: str):
69 return self._convert_output_dtype(result, original_image.dtype, func_name)
71 # ===== LIBRARY-SPECIFIC HELPER METHODS =====
72 def _convert_input_dtype(self, image, func_name):
73 """Internal dtype conversion logic."""
74 if func_name in self._BINARY_FUNCTIONS:
75 return ((image > 0.5) * 255).astype(np.uint8)
76 elif func_name in self._UINT8_FUNCTIONS:
77 return (np.clip(image, 0, 1) * 255).astype(np.uint8)
78 return image
80 def _convert_output_dtype(self, result, original_dtype, func_name):
81 """Internal output dtype conversion."""
82 if func_name in self._BINARY_FUNCTIONS or func_name in self._UINT8_FUNCTIONS:
83 if result.dtype != original_dtype:
84 if result.dtype == np.uint8 and original_dtype == np.float32:
85 return result.astype(np.float32) / 255.0
86 elif result.dtype == np.bool_ and original_dtype == np.float32:
87 return result.astype(np.float32)
88 return result
90 # ===== LIBRARY-SPECIFIC IMPLEMENTATIONS =====
91 def _stack_2d_results(self, func, test_3d):
92 """Stack 2D results using CLE."""
93 results = [func(test_3d[z]) for z in range(test_3d.shape[0])]
94 return cle.concatenate_along_z(*results)
96 def _arrays_close(self, arr1, arr2):
97 """Compare arrays using CLE."""
98 return np.allclose(arr1.get(), arr2.get(), rtol=1e-5, atol=1e-8)
100 def _expand_2d_to_3d(self, array_2d):
101 """Expand 2D array to 3D using CLE concatenation."""
102 temp = cle.concatenate_along_z(array_2d, array_2d)
103 return temp[0:1, :, :]