Coverage for openhcs/core/memory/converters.py: 5.6%

82 statements  

« prev     ^ index     » next       coverage.py v7.10.3, created at 2025-08-14 05:57 +0000

1""" 

2Memory conversion functions for OpenHCS. 

3 

4This module provides functions for converting between different memory types, 

5enforcing Clause 65 (Fail Loudly), Clause 88 (No Inferred Capabilities), 

6and Clause 251 (Declarative Memory Conversion). 

7""" 

8 

9from typing import Any 

10 

11from openhcs.constants.constants import MemoryType 

12 

13from .conversion_functions import (_cupy_to_jax, _cupy_to_numpy, 

14 _cupy_to_pyclesperanto, _cupy_to_tensorflow, _cupy_to_torch, 

15 _jax_to_cupy, _jax_to_jax, _jax_to_numpy, _jax_to_pyclesperanto, 

16 _jax_to_tensorflow, _jax_to_torch, 

17 _numpy_to_cupy, _numpy_to_jax, 

18 _numpy_to_pyclesperanto, _numpy_to_tensorflow, _numpy_to_torch, 

19 _pyclesperanto_to_cupy, _pyclesperanto_to_jax, _pyclesperanto_to_numpy, 

20 _pyclesperanto_to_pyclesperanto, _pyclesperanto_to_tensorflow, _pyclesperanto_to_torch, 

21 _tensorflow_to_cupy, _tensorflow_to_jax, _tensorflow_to_pyclesperanto, 

22 _tensorflow_to_numpy, _tensorflow_to_torch, 

23 _torch_to_cupy, _torch_to_jax, _torch_to_pyclesperanto, 

24 _torch_to_numpy, _torch_to_tensorflow) 

25 

26 

27def validate_memory_type(memory_type: str) -> None: 

28 """ 

29 Validate that a memory type is supported. 

30 

31 Args: 

32 memory_type: The memory type to validate 

33 

34 Raises: 

35 ValueError: If the memory type is not supported 

36 """ 

37 if memory_type not in [m.value for m in MemoryType]: 

38 raise ValueError( 

39 f"Unsupported memory type: {memory_type}. " 

40 f"Supported types are: {', '.join([m.value for m in MemoryType])}" 

41 ) 

42 

43 

44def validate_data_compatibility(data: Any, memory_type: str) -> None: 

45 """ 

46 Validate that data is compatible with a memory type. 

47 

48 Args: 

49 data: The data to validate 

50 memory_type: The memory type to validate against 

51 

52 Raises: 

53 ValueError: If the data is not compatible with the memory type 

54 """ 

55 # This is a placeholder for future validation logic 

56 # Currently, we don't have a way to validate data compatibility 

57 # without importing the memory type modules 

58 pass 

59 

60 

61def convert_memory( 

62 data: Any, 

63 source_type: str, 

64 target_type: str, 

65 gpu_id: int, 

66 allow_cpu_roundtrip: bool = False, 

67) -> Any: 

68 """ 

69 Convert data between memory types. 

70 

71 Args: 

72 data: The data to convert 

73 source_type: The source memory type 

74 target_type: The target memory type 

75 gpu_id: The target GPU device ID (required) 

76 allow_cpu_roundtrip: Whether to allow fallback to CPU roundtrip 

77 

78 Returns: 

79 The converted data 

80 

81 Raises: 

82 ValueError: If source_type or target_type is not supported 

83 MemoryConversionError: If conversion fails 

84 """ 

85 # If source and target types are the same, return the data as is 

86 if source_type == target_type: 86 ↛ 90line 86 didn't jump to line 90 because the condition on line 86 was always true

87 return data 

88 

89 # NumPy to X conversions 

90 if source_type == MemoryType.NUMPY.value: 

91 if target_type == MemoryType.CUPY.value: 

92 return _numpy_to_cupy(data, gpu_id) 

93 elif target_type == MemoryType.TORCH.value: 

94 return _numpy_to_torch(data, gpu_id) 

95 elif target_type == MemoryType.TENSORFLOW.value: 

96 return _numpy_to_tensorflow(data, gpu_id) 

97 elif target_type == MemoryType.JAX.value: 

98 return _numpy_to_jax(data, gpu_id) 

99 elif target_type == MemoryType.PYCLESPERANTO.value: 

100 return _numpy_to_pyclesperanto(data, gpu_id) 

101 

102 # CuPy to X conversions 

103 elif source_type == MemoryType.CUPY.value: 

104 if target_type == MemoryType.NUMPY.value: 

105 return _cupy_to_numpy(data) 

106 elif target_type == MemoryType.TORCH.value: 

107 return _cupy_to_torch(data, allow_cpu_roundtrip, gpu_id) 

108 elif target_type == MemoryType.TENSORFLOW.value: 

109 return _cupy_to_tensorflow(data, allow_cpu_roundtrip, gpu_id) 

110 elif target_type == MemoryType.JAX.value: 

111 return _cupy_to_jax(data, allow_cpu_roundtrip, gpu_id) 

112 elif target_type == MemoryType.PYCLESPERANTO.value: 

113 return _cupy_to_pyclesperanto(data, allow_cpu_roundtrip, gpu_id) 

114 

115 # PyTorch to X conversions 

116 elif source_type == MemoryType.TORCH.value: 

117 if target_type == MemoryType.NUMPY.value: 

118 return _torch_to_numpy(data) 

119 elif target_type == MemoryType.CUPY.value: 

120 return _torch_to_cupy(data, allow_cpu_roundtrip, gpu_id) 

121 elif target_type == MemoryType.TENSORFLOW.value: 

122 return _torch_to_tensorflow(data, allow_cpu_roundtrip, gpu_id) 

123 elif target_type == MemoryType.JAX.value: 

124 return _torch_to_jax(data, allow_cpu_roundtrip, gpu_id) 

125 elif target_type == MemoryType.PYCLESPERANTO.value: 

126 return _torch_to_pyclesperanto(data, allow_cpu_roundtrip, gpu_id) 

127 

128 # TensorFlow to X conversions 

129 elif source_type == MemoryType.TENSORFLOW.value: 

130 if target_type == MemoryType.NUMPY.value: 

131 return _tensorflow_to_numpy(data) 

132 elif target_type == MemoryType.CUPY.value: 

133 return _tensorflow_to_cupy(data, allow_cpu_roundtrip, gpu_id) 

134 elif target_type == MemoryType.TORCH.value: 

135 return _tensorflow_to_torch(data, allow_cpu_roundtrip, gpu_id) 

136 elif target_type == MemoryType.JAX.value: 

137 return _tensorflow_to_jax(data, allow_cpu_roundtrip, gpu_id) 

138 elif target_type == MemoryType.PYCLESPERANTO.value: 

139 return _tensorflow_to_pyclesperanto(data, allow_cpu_roundtrip, gpu_id) 

140 

141 # JAX to X conversions 

142 elif source_type == MemoryType.JAX.value: 

143 if target_type == MemoryType.NUMPY.value: 

144 return _jax_to_numpy(data) 

145 elif target_type == MemoryType.CUPY.value: 

146 return _jax_to_cupy(data, allow_cpu_roundtrip, gpu_id) 

147 elif target_type == MemoryType.TORCH.value: 

148 return _jax_to_torch(data, allow_cpu_roundtrip, gpu_id) 

149 elif target_type == MemoryType.TENSORFLOW.value: 

150 return _jax_to_tensorflow(data, allow_cpu_roundtrip, gpu_id) 

151 elif target_type == MemoryType.JAX.value: 

152 return _jax_to_jax(data, gpu_id) 

153 elif target_type == MemoryType.PYCLESPERANTO.value: 

154 return _jax_to_pyclesperanto(data, allow_cpu_roundtrip, gpu_id) 

155 

156 # pyclesperanto to X conversions 

157 elif source_type == MemoryType.PYCLESPERANTO.value: 

158 if target_type == MemoryType.NUMPY.value: 

159 return _pyclesperanto_to_numpy(data) 

160 elif target_type == MemoryType.CUPY.value: 

161 return _pyclesperanto_to_cupy(data, allow_cpu_roundtrip, gpu_id) 

162 elif target_type == MemoryType.TORCH.value: 

163 return _pyclesperanto_to_torch(data, allow_cpu_roundtrip, gpu_id) 

164 elif target_type == MemoryType.TENSORFLOW.value: 

165 return _pyclesperanto_to_tensorflow(data, allow_cpu_roundtrip, gpu_id) 

166 elif target_type == MemoryType.JAX.value: 

167 return _pyclesperanto_to_jax(data, allow_cpu_roundtrip, gpu_id) 

168 elif target_type == MemoryType.PYCLESPERANTO.value: 

169 return _pyclesperanto_to_pyclesperanto(data) 

170 

171 # If we get here, the conversion is not supported 

172 raise ValueError( 

173 f"Unsupported memory conversion: {source_type} -> {target_type}" 

174 )