amulet-core 1.9.19__py3-none-any.whl → 1.9.20__py3-none-any.whl

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.

Potentially problematic release.


This version of amulet-core might be problematic. Click here for more details.

Files changed (198) hide show
  1. amulet/__init__.py +27 -27
  2. amulet/__pyinstaller/__init__.py +2 -2
  3. amulet/__pyinstaller/hook-amulet.py +4 -4
  4. amulet/_version.py +21 -21
  5. amulet/api/__init__.py +2 -2
  6. amulet/api/abstract_base_entity.py +128 -128
  7. amulet/api/block.py +630 -630
  8. amulet/api/block_entity.py +71 -71
  9. amulet/api/cache.py +107 -107
  10. amulet/api/chunk/__init__.py +6 -6
  11. amulet/api/chunk/biomes.py +207 -207
  12. amulet/api/chunk/block_entity_dict.py +175 -175
  13. amulet/api/chunk/blocks.py +46 -46
  14. amulet/api/chunk/chunk.py +389 -389
  15. amulet/api/chunk/entity_list.py +75 -75
  16. amulet/api/chunk/status.py +167 -167
  17. amulet/api/data_types/__init__.py +4 -4
  18. amulet/api/data_types/generic_types.py +4 -4
  19. amulet/api/data_types/operation_types.py +16 -16
  20. amulet/api/data_types/world_types.py +49 -49
  21. amulet/api/data_types/wrapper_types.py +71 -71
  22. amulet/api/entity.py +74 -74
  23. amulet/api/errors.py +119 -119
  24. amulet/api/history/__init__.py +36 -36
  25. amulet/api/history/base/__init__.py +3 -3
  26. amulet/api/history/base/base_history.py +26 -26
  27. amulet/api/history/base/history_manager.py +63 -63
  28. amulet/api/history/base/revision_manager.py +73 -73
  29. amulet/api/history/changeable.py +15 -15
  30. amulet/api/history/data_types.py +7 -7
  31. amulet/api/history/history_manager/__init__.py +3 -3
  32. amulet/api/history/history_manager/container.py +102 -102
  33. amulet/api/history/history_manager/database.py +279 -279
  34. amulet/api/history/history_manager/meta.py +93 -93
  35. amulet/api/history/history_manager/object.py +116 -116
  36. amulet/api/history/revision_manager/__init__.py +2 -2
  37. amulet/api/history/revision_manager/disk.py +33 -33
  38. amulet/api/history/revision_manager/ram.py +12 -12
  39. amulet/api/item.py +75 -75
  40. amulet/api/level/__init__.py +4 -4
  41. amulet/api/level/base_level/__init__.py +1 -1
  42. amulet/api/level/base_level/base_level.py +1035 -1026
  43. amulet/api/level/base_level/chunk_manager.py +227 -227
  44. amulet/api/level/base_level/clone.py +389 -389
  45. amulet/api/level/base_level/player_manager.py +101 -101
  46. amulet/api/level/immutable_structure/__init__.py +1 -1
  47. amulet/api/level/immutable_structure/immutable_structure.py +94 -94
  48. amulet/api/level/immutable_structure/void_format_wrapper.py +117 -117
  49. amulet/api/level/structure.py +22 -22
  50. amulet/api/level/world.py +19 -19
  51. amulet/api/partial_3d_array/__init__.py +2 -2
  52. amulet/api/partial_3d_array/base_partial_3d_array.py +263 -263
  53. amulet/api/partial_3d_array/bounded_partial_3d_array.py +528 -528
  54. amulet/api/partial_3d_array/data_types.py +15 -15
  55. amulet/api/partial_3d_array/unbounded_partial_3d_array.py +229 -229
  56. amulet/api/partial_3d_array/util.py +152 -152
  57. amulet/api/player.py +65 -65
  58. amulet/api/registry/__init__.py +2 -2
  59. amulet/api/registry/base_registry.py +34 -34
  60. amulet/api/registry/biome_manager.py +153 -153
  61. amulet/api/registry/block_manager.py +156 -156
  62. amulet/api/selection/__init__.py +2 -2
  63. amulet/api/selection/abstract_selection.py +315 -315
  64. amulet/api/selection/box.py +805 -805
  65. amulet/api/selection/group.py +488 -488
  66. amulet/api/structure.py +37 -37
  67. amulet/api/wrapper/__init__.py +8 -8
  68. amulet/api/wrapper/chunk/interface.py +441 -441
  69. amulet/api/wrapper/chunk/translator.py +567 -567
  70. amulet/api/wrapper/format_wrapper.py +772 -772
  71. amulet/api/wrapper/structure_format_wrapper.py +116 -116
  72. amulet/api/wrapper/world_format_wrapper.py +63 -63
  73. amulet/level/__init__.py +1 -1
  74. amulet/level/formats/anvil_forge_world.py +40 -40
  75. amulet/level/formats/anvil_world/__init__.py +3 -3
  76. amulet/level/formats/anvil_world/_sector_manager.py +291 -384
  77. amulet/level/formats/anvil_world/data_pack/__init__.py +2 -2
  78. amulet/level/formats/anvil_world/data_pack/data_pack.py +224 -224
  79. amulet/level/formats/anvil_world/data_pack/data_pack_manager.py +77 -77
  80. amulet/level/formats/anvil_world/dimension.py +177 -177
  81. amulet/level/formats/anvil_world/format.py +769 -769
  82. amulet/level/formats/anvil_world/region.py +384 -384
  83. amulet/level/formats/construction/__init__.py +3 -3
  84. amulet/level/formats/construction/format_wrapper.py +515 -515
  85. amulet/level/formats/construction/interface.py +134 -134
  86. amulet/level/formats/construction/section.py +60 -60
  87. amulet/level/formats/construction/util.py +165 -165
  88. amulet/level/formats/leveldb_world/__init__.py +3 -3
  89. amulet/level/formats/leveldb_world/chunk.py +33 -33
  90. amulet/level/formats/leveldb_world/dimension.py +385 -419
  91. amulet/level/formats/leveldb_world/format.py +659 -641
  92. amulet/level/formats/leveldb_world/interface/chunk/__init__.py +36 -36
  93. amulet/level/formats/leveldb_world/interface/chunk/base_leveldb_interface.py +836 -836
  94. amulet/level/formats/leveldb_world/interface/chunk/generate_interface.py +31 -31
  95. amulet/level/formats/leveldb_world/interface/chunk/leveldb_0.py +30 -30
  96. amulet/level/formats/leveldb_world/interface/chunk/leveldb_1.py +12 -12
  97. amulet/level/formats/leveldb_world/interface/chunk/leveldb_10.py +12 -12
  98. amulet/level/formats/leveldb_world/interface/chunk/leveldb_11.py +12 -12
  99. amulet/level/formats/leveldb_world/interface/chunk/leveldb_12.py +12 -12
  100. amulet/level/formats/leveldb_world/interface/chunk/leveldb_13.py +12 -12
  101. amulet/level/formats/leveldb_world/interface/chunk/leveldb_14.py +12 -12
  102. amulet/level/formats/leveldb_world/interface/chunk/leveldb_15.py +12 -12
  103. amulet/level/formats/leveldb_world/interface/chunk/leveldb_16.py +12 -12
  104. amulet/level/formats/leveldb_world/interface/chunk/leveldb_17.py +12 -12
  105. amulet/level/formats/leveldb_world/interface/chunk/leveldb_18.py +12 -12
  106. amulet/level/formats/leveldb_world/interface/chunk/leveldb_19.py +12 -12
  107. amulet/level/formats/leveldb_world/interface/chunk/leveldb_2.py +12 -12
  108. amulet/level/formats/leveldb_world/interface/chunk/leveldb_20.py +12 -12
  109. amulet/level/formats/leveldb_world/interface/chunk/leveldb_21.py +12 -12
  110. amulet/level/formats/leveldb_world/interface/chunk/leveldb_22.py +12 -12
  111. amulet/level/formats/leveldb_world/interface/chunk/leveldb_23.py +10 -10
  112. amulet/level/formats/leveldb_world/interface/chunk/leveldb_24.py +10 -10
  113. amulet/level/formats/leveldb_world/interface/chunk/leveldb_25.py +24 -24
  114. amulet/level/formats/leveldb_world/interface/chunk/leveldb_26.py +10 -10
  115. amulet/level/formats/leveldb_world/interface/chunk/leveldb_27.py +10 -10
  116. amulet/level/formats/leveldb_world/interface/chunk/leveldb_28.py +10 -10
  117. amulet/level/formats/leveldb_world/interface/chunk/leveldb_29.py +33 -33
  118. amulet/level/formats/leveldb_world/interface/chunk/leveldb_3.py +57 -57
  119. amulet/level/formats/leveldb_world/interface/chunk/leveldb_30.py +10 -10
  120. amulet/level/formats/leveldb_world/interface/chunk/leveldb_31.py +10 -10
  121. amulet/level/formats/leveldb_world/interface/chunk/leveldb_32.py +10 -10
  122. amulet/level/formats/leveldb_world/interface/chunk/leveldb_33.py +10 -10
  123. amulet/level/formats/leveldb_world/interface/chunk/leveldb_34.py +10 -10
  124. amulet/level/formats/leveldb_world/interface/chunk/leveldb_35.py +10 -10
  125. amulet/level/formats/leveldb_world/interface/chunk/leveldb_36.py +10 -10
  126. amulet/level/formats/leveldb_world/interface/chunk/leveldb_37.py +10 -10
  127. amulet/level/formats/leveldb_world/interface/chunk/leveldb_38.py +10 -10
  128. amulet/level/formats/leveldb_world/interface/chunk/leveldb_39.py +12 -12
  129. amulet/level/formats/leveldb_world/interface/chunk/leveldb_4.py +12 -12
  130. amulet/level/formats/leveldb_world/interface/chunk/leveldb_40.py +16 -16
  131. amulet/level/formats/leveldb_world/interface/chunk/leveldb_5.py +12 -12
  132. amulet/level/formats/leveldb_world/interface/chunk/leveldb_6.py +12 -12
  133. amulet/level/formats/leveldb_world/interface/chunk/leveldb_7.py +12 -12
  134. amulet/level/formats/leveldb_world/interface/chunk/leveldb_8.py +180 -180
  135. amulet/level/formats/leveldb_world/interface/chunk/leveldb_9.py +18 -18
  136. amulet/level/formats/leveldb_world/interface/chunk/leveldb_chunk_versions.py +79 -79
  137. amulet/level/formats/mcstructure/__init__.py +3 -3
  138. amulet/level/formats/mcstructure/chunk.py +50 -50
  139. amulet/level/formats/mcstructure/format_wrapper.py +408 -408
  140. amulet/level/formats/mcstructure/interface.py +175 -175
  141. amulet/level/formats/schematic/__init__.py +3 -3
  142. amulet/level/formats/schematic/chunk.py +55 -55
  143. amulet/level/formats/schematic/data_types.py +4 -4
  144. amulet/level/formats/schematic/format_wrapper.py +373 -373
  145. amulet/level/formats/schematic/interface.py +142 -142
  146. amulet/level/formats/sponge_schem/__init__.py +4 -4
  147. amulet/level/formats/sponge_schem/chunk.py +62 -62
  148. amulet/level/formats/sponge_schem/format_wrapper.py +463 -463
  149. amulet/level/formats/sponge_schem/interface.py +118 -118
  150. amulet/level/formats/sponge_schem/varint/__init__.py +1 -1
  151. amulet/level/formats/sponge_schem/varint/varint.py +87 -87
  152. amulet/level/interfaces/chunk/anvil/anvil_0.py +72 -72
  153. amulet/level/interfaces/chunk/anvil/anvil_1444.py +336 -336
  154. amulet/level/interfaces/chunk/anvil/anvil_1466.py +94 -94
  155. amulet/level/interfaces/chunk/anvil/anvil_1467.py +37 -37
  156. amulet/level/interfaces/chunk/anvil/anvil_1484.py +20 -20
  157. amulet/level/interfaces/chunk/anvil/anvil_1503.py +20 -20
  158. amulet/level/interfaces/chunk/anvil/anvil_1519.py +34 -34
  159. amulet/level/interfaces/chunk/anvil/anvil_1901.py +20 -20
  160. amulet/level/interfaces/chunk/anvil/anvil_1908.py +20 -20
  161. amulet/level/interfaces/chunk/anvil/anvil_1912.py +21 -21
  162. amulet/level/interfaces/chunk/anvil/anvil_1934.py +20 -20
  163. amulet/level/interfaces/chunk/anvil/anvil_2203.py +69 -69
  164. amulet/level/interfaces/chunk/anvil/anvil_2529.py +19 -19
  165. amulet/level/interfaces/chunk/anvil/anvil_2681.py +76 -76
  166. amulet/level/interfaces/chunk/anvil/anvil_2709.py +19 -19
  167. amulet/level/interfaces/chunk/anvil/anvil_2844.py +267 -267
  168. amulet/level/interfaces/chunk/anvil/anvil_3463.py +19 -19
  169. amulet/level/interfaces/chunk/anvil/anvil_na.py +607 -607
  170. amulet/level/interfaces/chunk/anvil/base_anvil_interface.py +326 -326
  171. amulet/level/load.py +59 -59
  172. amulet/level/loader.py +95 -95
  173. amulet/level/translators/chunk/bedrock/__init__.py +267 -267
  174. amulet/level/translators/chunk/bedrock/bedrock_nbt_blockstate_translator.py +46 -46
  175. amulet/level/translators/chunk/bedrock/bedrock_numerical_translator.py +39 -39
  176. amulet/level/translators/chunk/bedrock/bedrock_psudo_numerical_translator.py +37 -37
  177. amulet/level/translators/chunk/java/java_1_18_translator.py +40 -40
  178. amulet/level/translators/chunk/java/java_blockstate_translator.py +94 -94
  179. amulet/level/translators/chunk/java/java_numerical_translator.py +62 -62
  180. amulet/libs/leveldb/__init__.py +7 -7
  181. amulet/operations/__init__.py +5 -5
  182. amulet/operations/clone.py +18 -18
  183. amulet/operations/delete_chunk.py +32 -32
  184. amulet/operations/fill.py +30 -30
  185. amulet/operations/paste.py +65 -65
  186. amulet/operations/replace.py +58 -58
  187. amulet/utils/__init__.py +14 -14
  188. amulet/utils/format_utils.py +41 -41
  189. amulet/utils/generator.py +15 -15
  190. amulet/utils/matrix.py +243 -243
  191. amulet/utils/numpy_helpers.py +46 -46
  192. amulet/utils/world_utils.py +349 -349
  193. {amulet_core-1.9.19.dist-info → amulet_core-1.9.20.dist-info}/METADATA +97 -97
  194. amulet_core-1.9.20.dist-info/RECORD +208 -0
  195. amulet_core-1.9.19.dist-info/RECORD +0 -208
  196. {amulet_core-1.9.19.dist-info → amulet_core-1.9.20.dist-info}/WHEEL +0 -0
  197. {amulet_core-1.9.19.dist-info → amulet_core-1.9.20.dist-info}/entry_points.txt +0 -0
  198. {amulet_core-1.9.19.dist-info → amulet_core-1.9.20.dist-info}/top_level.txt +0 -0
amulet/api/level/world.py CHANGED
@@ -1,19 +1,19 @@
1
- from __future__ import annotations
2
-
3
- from .base_level import BaseLevel
4
- from amulet.api.wrapper import WorldFormatWrapper
5
-
6
-
7
- class World(BaseLevel):
8
- """
9
- Class that handles world editing of any world format via an separate and flexible data format
10
- """
11
-
12
- def __init__(self, directory: str, world_wrapper: WorldFormatWrapper):
13
- assert isinstance(world_wrapper, WorldFormatWrapper)
14
- super().__init__(directory, world_wrapper)
15
-
16
- @property
17
- def level_wrapper(self) -> "WorldFormatWrapper":
18
- """A class to access data directly from the level."""
19
- return self._level_wrapper
1
+ from __future__ import annotations
2
+
3
+ from .base_level import BaseLevel
4
+ from amulet.api.wrapper import WorldFormatWrapper
5
+
6
+
7
+ class World(BaseLevel):
8
+ """
9
+ Class that handles world editing of any world format via an separate and flexible data format
10
+ """
11
+
12
+ def __init__(self, directory: str, world_wrapper: WorldFormatWrapper):
13
+ assert isinstance(world_wrapper, WorldFormatWrapper)
14
+ super().__init__(directory, world_wrapper)
15
+
16
+ @property
17
+ def level_wrapper(self) -> "WorldFormatWrapper":
18
+ """A class to access data directly from the level."""
19
+ return self._level_wrapper
@@ -1,2 +1,2 @@
1
- from .unbounded_partial_3d_array import UnboundedPartial3DArray
2
- from .bounded_partial_3d_array import BoundedPartial3DArray
1
+ from .unbounded_partial_3d_array import UnboundedPartial3DArray
2
+ from .bounded_partial_3d_array import BoundedPartial3DArray
@@ -1,263 +1,263 @@
1
- from abc import ABC, abstractmethod
2
- from typing import Optional, Dict, Union, Tuple, Type, TYPE_CHECKING
3
- import numpy
4
-
5
- import copy
6
-
7
- from .util import get_sanitised_sliced_array_size
8
- from .data_types import DtypeType, UnpackedSlicesType, IntegerType
9
-
10
- if TYPE_CHECKING:
11
- from .unbounded_partial_3d_array import UnboundedPartial3DArray
12
-
13
-
14
- class BasePartial3DArray(ABC):
15
- """Do not use this class directly. Use UnboundedPartial3DArray or BoundedPartial3DArray"""
16
-
17
- _sections: Dict[int, numpy.ndarray]
18
-
19
- def __init__(
20
- self,
21
- dtype: DtypeType,
22
- default_value: Union[int, bool],
23
- section_shape: Tuple[int, int, int],
24
- start: Tuple[Optional[int], Optional[int], Optional[int]],
25
- stop: Tuple[Optional[int], Optional[int], Optional[int]],
26
- step: Tuple[Optional[int], Optional[int], Optional[int]],
27
- parent_array: Optional["UnboundedPartial3DArray"] = None,
28
- sections: Optional[Dict[int, numpy.ndarray]] = None,
29
- ):
30
- self._dtype = dtype
31
- self._default_value: Union[int, bool] = default_value
32
- self._section_shape = section_shape
33
- self._parent_array = parent_array
34
-
35
- self._size_x = None
36
- self._size_y = None
37
- self._size_z = None
38
-
39
- self._start_x, self._stop_x, self._step_x = start[0], stop[0], step[0]
40
- self._start_y, self._stop_y = start[1], stop[1]
41
- assert (self._start_y is None and self._stop_y is None) or (
42
- isinstance(self._start_y, int) and isinstance(self._stop_y, int)
43
- ), "y start and stop must both be None or ints"
44
- self._step_y = 1 if step[1] is None else step[1]
45
- if self.size_y == 0:
46
- self._stop_y = self._start_y
47
- self._start_z, self._stop_z, self._step_z = start[2], stop[2], step[2]
48
-
49
- if parent_array is None:
50
- # populate from sections
51
- self._sections = sections or {}
52
- for key, section in self._sections.items():
53
- if not isinstance(key, int):
54
- raise ValueError("All keys must be ints")
55
- if section.shape != self._section_shape:
56
- raise ValueError(
57
- f"The size of all sections must be equal to the section_shape. Expected shape {self._section_shape}, got {section.shape}"
58
- )
59
- if section.dtype != self._dtype:
60
- raise ValueError(
61
- f"The given dtype does not match the arrays given. Expected {self._default_value}, got {section.dtype}"
62
- )
63
-
64
- elif isinstance(parent_array, BasePartial3DArray):
65
- # populate from the array
66
- assert (
67
- parent_array.section_shape == self._section_shape
68
- ), "The parent section shape must match the given section_shape."
69
- assert (
70
- parent_array.dtype == self._dtype
71
- ), "The parent dtype must match the given dtype"
72
- self._sections = parent_array._sections
73
-
74
- else:
75
- raise Exception(
76
- f"{parent_array.__class__.__name__}({parent_array}) is not a valid input type for parent_array"
77
- )
78
-
79
- @property
80
- def start_x(self) -> int:
81
- """The minimum x value of the slice within the original array. Read Only"""
82
- return self._start_x
83
-
84
- @property
85
- def start_y(self) -> Optional[int]:
86
- """The minimum y value of the slice within the original array. Read Only"""
87
- return self._start_y
88
-
89
- @property
90
- def start_z(self) -> int:
91
- """The minimum z value of the slice within the original array. Read Only"""
92
- return self._start_z
93
-
94
- @property
95
- def start(self) -> Tuple[int, int, int]:
96
- """The minimum x, y and z of the slice within the original array. Read Only"""
97
- return self.start_x, self.start_y, self.start_z
98
-
99
- @property
100
- def stop_x(self) -> int:
101
- """The maximum x value of the slice within the original array. Read Only"""
102
- return self._stop_x
103
-
104
- @property
105
- def stop_y(self) -> Optional[int]:
106
- """The maximum y value of the slice within the original array. Read Only"""
107
- return self._stop_y
108
-
109
- @property
110
- def stop_z(self) -> int:
111
- """The maximum z value of the slice within the original array. Read Only"""
112
- return self._stop_z
113
-
114
- @property
115
- def stop(self) -> Tuple[int, int, int]:
116
- """The maximum x value of the slice within the original array. Read Only"""
117
- return self.stop_x, self.stop_y, self.stop_z
118
-
119
- @property
120
- def step_x(self) -> int:
121
- """The step count of the slice in the x axis. Read Only"""
122
- return self._step_x
123
-
124
- @property
125
- def step_y(self) -> int:
126
- """The step count of the slice in the y axis. Read Only"""
127
- return self._step_y
128
-
129
- @property
130
- def step_z(self) -> int:
131
- """The step count of the slice in the z axis. Read Only"""
132
- return self._step_z
133
-
134
- @property
135
- def step(self) -> Tuple[int, int, int]:
136
- """The step count of the slice in the x, y and z axis. Read Only"""
137
- return self.step_x, self.step_y, self.step_z
138
-
139
- @property
140
- def slice_x(self) -> slice:
141
- """The slice in the x axis into the original array. Read Only"""
142
- return slice(self.start_x, self.stop_x, self.step_x)
143
-
144
- @property
145
- def slice_y(self) -> slice:
146
- """The slice in the y axis into the original array. Read Only"""
147
- return slice(self.start_y, self.stop_y, self.step_y)
148
-
149
- @property
150
- def slice_z(self) -> slice:
151
- """The slice in the z axis into the original array. Read Only"""
152
- return slice(self.start_z, self.stop_z, self.step_z)
153
-
154
- @property
155
- def slices_tuple(self) -> UnpackedSlicesType:
156
- """The slices data in the x, y and z axis into the original array. Read Only"""
157
- return (
158
- (self.start_x, self.stop_x, self.step_x),
159
- (self.start_y, self.stop_y, self.step_y),
160
- (self.start_z, self.stop_z, self.step_z),
161
- )
162
-
163
- @property
164
- def size_x(self) -> int:
165
- """The size of the array in the x axis. Read Only"""
166
- if self._size_x is None:
167
- self._size_x = get_sanitised_sliced_array_size(
168
- self.start_x, self.stop_x, self.step_x
169
- )
170
- return self._size_x
171
-
172
- @property
173
- def size_y(self) -> Union[int, float]:
174
- """The size of the array in the y axis. Read Only"""
175
- if self._size_y is None:
176
- self._size_y = get_sanitised_sliced_array_size(
177
- self.start_y, self.stop_y, self.step_y
178
- )
179
- return self._size_y
180
-
181
- @property
182
- def size_z(self) -> int:
183
- """The size of the array in the z axis. Read Only"""
184
- if self._size_z is None:
185
- self._size_z = get_sanitised_sliced_array_size(
186
- self.start_z, self.stop_z, self.step_z
187
- )
188
- return self._size_z
189
-
190
- @property
191
- def shape(self) -> Tuple[int, Union[int, float], int]:
192
- """The size of the array in the x, y and z axis. Read Only"""
193
- return self.size_x, self.size_y, self.size_z
194
-
195
- @property
196
- def dtype(self) -> Type[numpy.dtype]:
197
- """The numpy dtype for the arrays. Read Only."""
198
- return self._dtype
199
-
200
- @property
201
- def default_value(self) -> Union[int, bool]:
202
- """The default value to populate undefined sections with. Read Only"""
203
- return self._default_value
204
-
205
- @property
206
- def section_shape(self) -> Tuple[int, int, int]:
207
- """The x, y and z size of a section in the original array."""
208
- return self._section_shape
209
-
210
- def _section_index(self, y: IntegerType) -> Tuple[IntegerType, IntegerType]:
211
- """
212
- Get the section index and location within the section of an absolute y coordinate.
213
-
214
- :param y: The absolute y coordinate.
215
- :return: The section index this coordinate is found in.
216
- """
217
- return y // self.section_shape[1], y % self.section_shape[1]
218
-
219
- @abstractmethod
220
- def __array__(self, dtype=None):
221
- raise NotImplementedError
222
-
223
- def __contains__(self, item: int):
224
- """
225
- Is a section array defined.
226
-
227
- >>> 5 in partial_array
228
- True
229
-
230
- :param item: The section index to test.
231
- :return: ``True`` if there is an array present for this section. ``False`` otherwise
232
- """
233
- return item in self._sections
234
-
235
- def __iter__(self):
236
- raise Exception(
237
- "Please use sections method if this is what you are trying to achieve"
238
- )
239
-
240
- @abstractmethod
241
- def __getitem__(self, item):
242
- raise NotImplementedError
243
-
244
- @abstractmethod
245
- def __setitem__(self, key, value):
246
- raise NotImplementedError
247
-
248
- def copy(self):
249
- return copy.copy(self)
250
-
251
- def __copy__(self):
252
- cls = self.__class__
253
- result = cls.__new__(cls)
254
- result.__dict__.update(self.__dict__)
255
- return result
256
-
257
- def __deepcopy__(self, memodict=None):
258
- cls = self.__class__
259
- result = cls.__new__(cls)
260
- memodict[id(self)] = result
261
- for k, v in self.__dict__.items():
262
- setattr(result, k, copy.deepcopy(v, memodict))
263
- return result
1
+ from abc import ABC, abstractmethod
2
+ from typing import Optional, Dict, Union, Tuple, Type, TYPE_CHECKING
3
+ import numpy
4
+
5
+ import copy
6
+
7
+ from .util import get_sanitised_sliced_array_size
8
+ from .data_types import DtypeType, UnpackedSlicesType, IntegerType
9
+
10
+ if TYPE_CHECKING:
11
+ from .unbounded_partial_3d_array import UnboundedPartial3DArray
12
+
13
+
14
+ class BasePartial3DArray(ABC):
15
+ """Do not use this class directly. Use UnboundedPartial3DArray or BoundedPartial3DArray"""
16
+
17
+ _sections: Dict[int, numpy.ndarray]
18
+
19
+ def __init__(
20
+ self,
21
+ dtype: DtypeType,
22
+ default_value: Union[int, bool],
23
+ section_shape: Tuple[int, int, int],
24
+ start: Tuple[Optional[int], Optional[int], Optional[int]],
25
+ stop: Tuple[Optional[int], Optional[int], Optional[int]],
26
+ step: Tuple[Optional[int], Optional[int], Optional[int]],
27
+ parent_array: Optional["UnboundedPartial3DArray"] = None,
28
+ sections: Optional[Dict[int, numpy.ndarray]] = None,
29
+ ):
30
+ self._dtype = dtype
31
+ self._default_value: Union[int, bool] = default_value
32
+ self._section_shape = section_shape
33
+ self._parent_array = parent_array
34
+
35
+ self._size_x = None
36
+ self._size_y = None
37
+ self._size_z = None
38
+
39
+ self._start_x, self._stop_x, self._step_x = start[0], stop[0], step[0]
40
+ self._start_y, self._stop_y = start[1], stop[1]
41
+ assert (self._start_y is None and self._stop_y is None) or (
42
+ isinstance(self._start_y, int) and isinstance(self._stop_y, int)
43
+ ), "y start and stop must both be None or ints"
44
+ self._step_y = 1 if step[1] is None else step[1]
45
+ if self.size_y == 0:
46
+ self._stop_y = self._start_y
47
+ self._start_z, self._stop_z, self._step_z = start[2], stop[2], step[2]
48
+
49
+ if parent_array is None:
50
+ # populate from sections
51
+ self._sections = sections or {}
52
+ for key, section in self._sections.items():
53
+ if not isinstance(key, int):
54
+ raise ValueError("All keys must be ints")
55
+ if section.shape != self._section_shape:
56
+ raise ValueError(
57
+ f"The size of all sections must be equal to the section_shape. Expected shape {self._section_shape}, got {section.shape}"
58
+ )
59
+ if section.dtype != self._dtype:
60
+ raise ValueError(
61
+ f"The given dtype does not match the arrays given. Expected {self._default_value}, got {section.dtype}"
62
+ )
63
+
64
+ elif isinstance(parent_array, BasePartial3DArray):
65
+ # populate from the array
66
+ assert (
67
+ parent_array.section_shape == self._section_shape
68
+ ), "The parent section shape must match the given section_shape."
69
+ assert (
70
+ parent_array.dtype == self._dtype
71
+ ), "The parent dtype must match the given dtype"
72
+ self._sections = parent_array._sections
73
+
74
+ else:
75
+ raise Exception(
76
+ f"{parent_array.__class__.__name__}({parent_array}) is not a valid input type for parent_array"
77
+ )
78
+
79
+ @property
80
+ def start_x(self) -> int:
81
+ """The minimum x value of the slice within the original array. Read Only"""
82
+ return self._start_x
83
+
84
+ @property
85
+ def start_y(self) -> Optional[int]:
86
+ """The minimum y value of the slice within the original array. Read Only"""
87
+ return self._start_y
88
+
89
+ @property
90
+ def start_z(self) -> int:
91
+ """The minimum z value of the slice within the original array. Read Only"""
92
+ return self._start_z
93
+
94
+ @property
95
+ def start(self) -> Tuple[int, int, int]:
96
+ """The minimum x, y and z of the slice within the original array. Read Only"""
97
+ return self.start_x, self.start_y, self.start_z
98
+
99
+ @property
100
+ def stop_x(self) -> int:
101
+ """The maximum x value of the slice within the original array. Read Only"""
102
+ return self._stop_x
103
+
104
+ @property
105
+ def stop_y(self) -> Optional[int]:
106
+ """The maximum y value of the slice within the original array. Read Only"""
107
+ return self._stop_y
108
+
109
+ @property
110
+ def stop_z(self) -> int:
111
+ """The maximum z value of the slice within the original array. Read Only"""
112
+ return self._stop_z
113
+
114
+ @property
115
+ def stop(self) -> Tuple[int, int, int]:
116
+ """The maximum x value of the slice within the original array. Read Only"""
117
+ return self.stop_x, self.stop_y, self.stop_z
118
+
119
+ @property
120
+ def step_x(self) -> int:
121
+ """The step count of the slice in the x axis. Read Only"""
122
+ return self._step_x
123
+
124
+ @property
125
+ def step_y(self) -> int:
126
+ """The step count of the slice in the y axis. Read Only"""
127
+ return self._step_y
128
+
129
+ @property
130
+ def step_z(self) -> int:
131
+ """The step count of the slice in the z axis. Read Only"""
132
+ return self._step_z
133
+
134
+ @property
135
+ def step(self) -> Tuple[int, int, int]:
136
+ """The step count of the slice in the x, y and z axis. Read Only"""
137
+ return self.step_x, self.step_y, self.step_z
138
+
139
+ @property
140
+ def slice_x(self) -> slice:
141
+ """The slice in the x axis into the original array. Read Only"""
142
+ return slice(self.start_x, self.stop_x, self.step_x)
143
+
144
+ @property
145
+ def slice_y(self) -> slice:
146
+ """The slice in the y axis into the original array. Read Only"""
147
+ return slice(self.start_y, self.stop_y, self.step_y)
148
+
149
+ @property
150
+ def slice_z(self) -> slice:
151
+ """The slice in the z axis into the original array. Read Only"""
152
+ return slice(self.start_z, self.stop_z, self.step_z)
153
+
154
+ @property
155
+ def slices_tuple(self) -> UnpackedSlicesType:
156
+ """The slices data in the x, y and z axis into the original array. Read Only"""
157
+ return (
158
+ (self.start_x, self.stop_x, self.step_x),
159
+ (self.start_y, self.stop_y, self.step_y),
160
+ (self.start_z, self.stop_z, self.step_z),
161
+ )
162
+
163
+ @property
164
+ def size_x(self) -> int:
165
+ """The size of the array in the x axis. Read Only"""
166
+ if self._size_x is None:
167
+ self._size_x = get_sanitised_sliced_array_size(
168
+ self.start_x, self.stop_x, self.step_x
169
+ )
170
+ return self._size_x
171
+
172
+ @property
173
+ def size_y(self) -> Union[int, float]:
174
+ """The size of the array in the y axis. Read Only"""
175
+ if self._size_y is None:
176
+ self._size_y = get_sanitised_sliced_array_size(
177
+ self.start_y, self.stop_y, self.step_y
178
+ )
179
+ return self._size_y
180
+
181
+ @property
182
+ def size_z(self) -> int:
183
+ """The size of the array in the z axis. Read Only"""
184
+ if self._size_z is None:
185
+ self._size_z = get_sanitised_sliced_array_size(
186
+ self.start_z, self.stop_z, self.step_z
187
+ )
188
+ return self._size_z
189
+
190
+ @property
191
+ def shape(self) -> Tuple[int, Union[int, float], int]:
192
+ """The size of the array in the x, y and z axis. Read Only"""
193
+ return self.size_x, self.size_y, self.size_z
194
+
195
+ @property
196
+ def dtype(self) -> Type[numpy.dtype]:
197
+ """The numpy dtype for the arrays. Read Only."""
198
+ return self._dtype
199
+
200
+ @property
201
+ def default_value(self) -> Union[int, bool]:
202
+ """The default value to populate undefined sections with. Read Only"""
203
+ return self._default_value
204
+
205
+ @property
206
+ def section_shape(self) -> Tuple[int, int, int]:
207
+ """The x, y and z size of a section in the original array."""
208
+ return self._section_shape
209
+
210
+ def _section_index(self, y: IntegerType) -> Tuple[IntegerType, IntegerType]:
211
+ """
212
+ Get the section index and location within the section of an absolute y coordinate.
213
+
214
+ :param y: The absolute y coordinate.
215
+ :return: The section index this coordinate is found in.
216
+ """
217
+ return y // self.section_shape[1], y % self.section_shape[1]
218
+
219
+ @abstractmethod
220
+ def __array__(self, dtype=None):
221
+ raise NotImplementedError
222
+
223
+ def __contains__(self, item: int):
224
+ """
225
+ Is a section array defined.
226
+
227
+ >>> 5 in partial_array
228
+ True
229
+
230
+ :param item: The section index to test.
231
+ :return: ``True`` if there is an array present for this section. ``False`` otherwise
232
+ """
233
+ return item in self._sections
234
+
235
+ def __iter__(self):
236
+ raise Exception(
237
+ "Please use sections method if this is what you are trying to achieve"
238
+ )
239
+
240
+ @abstractmethod
241
+ def __getitem__(self, item):
242
+ raise NotImplementedError
243
+
244
+ @abstractmethod
245
+ def __setitem__(self, key, value):
246
+ raise NotImplementedError
247
+
248
+ def copy(self):
249
+ return copy.copy(self)
250
+
251
+ def __copy__(self):
252
+ cls = self.__class__
253
+ result = cls.__new__(cls)
254
+ result.__dict__.update(self.__dict__)
255
+ return result
256
+
257
+ def __deepcopy__(self, memodict=None):
258
+ cls = self.__class__
259
+ result = cls.__new__(cls)
260
+ memodict[id(self)] = result
261
+ for k, v in self.__dict__.items():
262
+ setattr(result, k, copy.deepcopy(v, memodict))
263
+ return result