transformnd 0.8.0__tar.gz → 0.9.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.
- {transformnd-0.8.0 → transformnd-0.9.0}/PKG-INFO +1 -1
- {transformnd-0.8.0 → transformnd-0.9.0}/pyproject.toml +1 -1
- {transformnd-0.8.0 → transformnd-0.9.0}/pyproject.toml.orig +1 -1
- {transformnd-0.8.0 → transformnd-0.9.0}/src/transformnd/base.py +37 -8
- {transformnd-0.8.0 → transformnd-0.9.0}/src/transformnd/graph.py +14 -0
- {transformnd-0.8.0 → transformnd-0.9.0}/src/transformnd/transforms/simple.py +11 -0
- {transformnd-0.8.0 → transformnd-0.9.0}/README.md +0 -0
- {transformnd-0.8.0 → transformnd-0.9.0}/src/transformnd/__init__.py +0 -0
- {transformnd-0.8.0 → transformnd-0.9.0}/src/transformnd/adapters/__init__.py +0 -0
- {transformnd-0.8.0 → transformnd-0.9.0}/src/transformnd/adapters/base.py +0 -0
- {transformnd-0.8.0 → transformnd-0.9.0}/src/transformnd/adapters/bounding_box.py +0 -0
- {transformnd-0.8.0 → transformnd-0.9.0}/src/transformnd/adapters/pandas.py +0 -0
- {transformnd-0.8.0 → transformnd-0.9.0}/src/transformnd/adapters/polars.py +0 -0
- {transformnd-0.8.0 → transformnd-0.9.0}/src/transformnd/adapters/shapely.py +0 -0
- {transformnd-0.8.0 → transformnd-0.9.0}/src/transformnd/extents/__init__.py +0 -0
- {transformnd-0.8.0 → transformnd-0.9.0}/src/transformnd/extents/base.py +0 -0
- {transformnd-0.8.0 → transformnd-0.9.0}/src/transformnd/extents/bounding_box.py +0 -0
- {transformnd-0.8.0 → transformnd-0.9.0}/src/transformnd/py.typed +0 -0
- {transformnd-0.8.0 → transformnd-0.9.0}/src/transformnd/spaced.py +0 -0
- {transformnd-0.8.0 → transformnd-0.9.0}/src/transformnd/transforms/__init__.py +0 -0
- {transformnd-0.8.0 → transformnd-0.9.0}/src/transformnd/transforms/affine.py +0 -0
- {transformnd-0.8.0 → transformnd-0.9.0}/src/transformnd/transforms/bijection.py +0 -0
- {transformnd-0.8.0 → transformnd-0.9.0}/src/transformnd/transforms/by_dimension.py +0 -0
- {transformnd-0.8.0 → transformnd-0.9.0}/src/transformnd/transforms/grid.py +0 -0
- {transformnd-0.8.0 → transformnd-0.9.0}/src/transformnd/transforms/map_axis.py +0 -0
- {transformnd-0.8.0 → transformnd-0.9.0}/src/transformnd/transforms/moving_least_squares.py +0 -0
- {transformnd-0.8.0 → transformnd-0.9.0}/src/transformnd/transforms/project_axis.py +0 -0
- {transformnd-0.8.0 → transformnd-0.9.0}/src/transformnd/transforms/reflection.py +0 -0
- {transformnd-0.8.0 → transformnd-0.9.0}/src/transformnd/transforms/thinplate.py +0 -0
- {transformnd-0.8.0 → transformnd-0.9.0}/src/transformnd/transforms/vector_field.py +0 -0
- {transformnd-0.8.0 → transformnd-0.9.0}/src/transformnd/types.py +0 -0
- {transformnd-0.8.0 → transformnd-0.9.0}/src/transformnd/util.py +0 -0
|
@@ -240,7 +240,11 @@ def as_transform_list(t: Transform[ArrayT]) -> list[Transform[ArrayT]]:
|
|
|
240
240
|
|
|
241
241
|
|
|
242
242
|
class TransformSequence(Transform[ArrayT], Sequence[Transform[ArrayT]]):
|
|
243
|
-
"""Chain transforms, applying one after another.
|
|
243
|
+
"""Chain transforms, applying one after another.
|
|
244
|
+
|
|
245
|
+
The `TransformSequence()` constructor takes a sequence of transforms which must not be empty.
|
|
246
|
+
Empty sequences can be handled with `TransformSequence.empty(ndim: int)`.
|
|
247
|
+
"""
|
|
244
248
|
|
|
245
249
|
def __init__(
|
|
246
250
|
self,
|
|
@@ -248,8 +252,10 @@ class TransformSequence(Transform[ArrayT], Sequence[Transform[ArrayT]]):
|
|
|
248
252
|
) -> None:
|
|
249
253
|
"""Combine transforms by chaining them.
|
|
250
254
|
|
|
251
|
-
|
|
252
|
-
|
|
255
|
+
Empty sequences raise an error;
|
|
256
|
+
use the `TransformSequence.empty(ndim)` constructor instead.
|
|
257
|
+
|
|
258
|
+
Also checks for consistent dimensionality.
|
|
253
259
|
|
|
254
260
|
Parameters
|
|
255
261
|
----------
|
|
@@ -260,11 +266,13 @@ class TransformSequence(Transform[ArrayT], Sequence[Transform[ArrayT]]):
|
|
|
260
266
|
Raises
|
|
261
267
|
------
|
|
262
268
|
ValueError
|
|
263
|
-
If spaces are incompatible.
|
|
269
|
+
If spaces are incompatible, or no spaces are given.
|
|
264
270
|
"""
|
|
265
271
|
ts = list(transforms)
|
|
266
272
|
if not ts:
|
|
267
|
-
raise ValueError(
|
|
273
|
+
raise ValueError(
|
|
274
|
+
"Empty transform sequence; use TransformSequence.empty(ndim)"
|
|
275
|
+
)
|
|
268
276
|
|
|
269
277
|
for idx, (t1, t2) in enumerate(pairwise(ts)):
|
|
270
278
|
if t1.ndims.target != t2.ndims.source:
|
|
@@ -280,6 +288,14 @@ class TransformSequence(Transform[ArrayT], Sequence[Transform[ArrayT]]):
|
|
|
280
288
|
|
|
281
289
|
self.transforms: list[Transform[ArrayT]] = ts
|
|
282
290
|
|
|
291
|
+
@classmethod
|
|
292
|
+
def empty(cls, ndim: int) -> Self:
|
|
293
|
+
from .transforms import Identity
|
|
294
|
+
|
|
295
|
+
out = cls([Identity(ndim)])
|
|
296
|
+
out.transforms.pop()
|
|
297
|
+
return out
|
|
298
|
+
|
|
283
299
|
def __iter__(self) -> Iterator[Transform[ArrayT]]:
|
|
284
300
|
"""Iterate through component transforms.
|
|
285
301
|
|
|
@@ -299,6 +315,9 @@ class TransformSequence(Transform[ArrayT], Sequence[Transform[ArrayT]]):
|
|
|
299
315
|
return len(self.transforms)
|
|
300
316
|
|
|
301
317
|
def invert(self) -> Transform[ArrayT] | None:
|
|
318
|
+
if self.is_empty():
|
|
319
|
+
return type(self).empty(self.ndims.source)
|
|
320
|
+
|
|
302
321
|
try:
|
|
303
322
|
transforms = [~t for t in reversed(self.transforms)]
|
|
304
323
|
except NotImplementedError:
|
|
@@ -314,7 +333,8 @@ class TransformSequence(Transform[ArrayT], Sequence[Transform[ArrayT]]):
|
|
|
314
333
|
|
|
315
334
|
def to_device(self, xp: ModuleType, device: str | None = None) -> Self:
|
|
316
335
|
result = copy(self)
|
|
317
|
-
|
|
336
|
+
if not self.is_empty():
|
|
337
|
+
result.transforms = [t.to_device(xp, device) for t in self.transforms]
|
|
318
338
|
return result
|
|
319
339
|
|
|
320
340
|
def __str__(self) -> str:
|
|
@@ -329,10 +349,16 @@ class TransformSequence(Transform[ArrayT], Sequence[Transform[ArrayT]]):
|
|
|
329
349
|
def is_identity(self) -> bool:
|
|
330
350
|
return all(t.is_identity() for t in self)
|
|
331
351
|
|
|
352
|
+
def is_empty(self) -> bool:
|
|
353
|
+
return not self.transforms
|
|
354
|
+
|
|
332
355
|
def flatten(self, drop_inverse: bool = True) -> Self:
|
|
333
356
|
"""Flatten nested sequences."""
|
|
334
357
|
from .transforms.bijection import Bijection
|
|
335
358
|
|
|
359
|
+
if self.is_empty():
|
|
360
|
+
return copy(self)
|
|
361
|
+
|
|
336
362
|
out: list[Transform[ArrayT]] = []
|
|
337
363
|
|
|
338
364
|
for t in self.transforms:
|
|
@@ -357,7 +383,8 @@ class TransformSequence(Transform[ArrayT], Sequence[Transform[ArrayT]]):
|
|
|
357
383
|
Does not check whether transforms invert each other,
|
|
358
384
|
e.g. `Translation(1) | Translation(-1)`.
|
|
359
385
|
"""
|
|
360
|
-
|
|
386
|
+
if self.is_empty():
|
|
387
|
+
return copy(self)
|
|
361
388
|
|
|
362
389
|
out: list[Transform[ArrayT]] = []
|
|
363
390
|
affine = None
|
|
@@ -383,11 +410,13 @@ class TransformSequence(Transform[ArrayT], Sequence[Transform[ArrayT]]):
|
|
|
383
410
|
add_to_output(affine, out)
|
|
384
411
|
|
|
385
412
|
if not out:
|
|
386
|
-
|
|
413
|
+
return type(self).empty(self.ndims.source)
|
|
387
414
|
|
|
388
415
|
return type(self)(out)
|
|
389
416
|
|
|
390
417
|
def to_affine(self) -> Affine[ArrayT] | None:
|
|
418
|
+
if self.is_empty():
|
|
419
|
+
return Affine.identity(self.ndims.source) # type:ignore
|
|
391
420
|
simple = self.simplify(True)
|
|
392
421
|
if len(simple) != 1:
|
|
393
422
|
return None
|
|
@@ -225,7 +225,21 @@ class TransformGraph(Generic[ArrayT, SpaceRef]):
|
|
|
225
225
|
-------
|
|
226
226
|
TransformSequence[ArrayT]
|
|
227
227
|
The shortest transform sequence between the spaces.
|
|
228
|
+
|
|
229
|
+
Raises
|
|
230
|
+
------
|
|
231
|
+
ValueError
|
|
232
|
+
Unknown source or target space.
|
|
228
233
|
"""
|
|
234
|
+
src_ndim = self.ndim(source_space)
|
|
235
|
+
if src_ndim is None:
|
|
236
|
+
raise ValueError(f"Unknown source space {source_space}")
|
|
237
|
+
elif source_space == target_space:
|
|
238
|
+
return TransformSequence.empty(src_ndim) # type:ignore
|
|
239
|
+
|
|
240
|
+
if self.ndim(target_space) is None:
|
|
241
|
+
raise ValueError(f"Unknown target space {source_space}")
|
|
242
|
+
|
|
229
243
|
path = nx.shortest_path(self.graph, source_space, target_space, weight) # type:ignore
|
|
230
244
|
transforms = []
|
|
231
245
|
if len(path) == 1:
|
|
@@ -45,6 +45,9 @@ class Identity(Transform[ArrayT]):
|
|
|
45
45
|
def __str__(self) -> str:
|
|
46
46
|
return f"{super().__str__()}({self.ndims.source})"
|
|
47
47
|
|
|
48
|
+
def is_identity(self) -> bool:
|
|
49
|
+
return True
|
|
50
|
+
|
|
48
51
|
|
|
49
52
|
class Translate(Transform[ArrayT]):
|
|
50
53
|
"""Translate coordinates by addition."""
|
|
@@ -72,6 +75,10 @@ class Translate(Transform[ArrayT]):
|
|
|
72
75
|
)
|
|
73
76
|
super().__init__(NDims(len(self.translation), len(self.translation)))
|
|
74
77
|
|
|
78
|
+
def is_identity(self) -> bool:
|
|
79
|
+
xp = array_namespace(self.translation)
|
|
80
|
+
return xp.all(self.translation == 0)
|
|
81
|
+
|
|
75
82
|
def to_affine(self) -> Affine[ArrayT]:
|
|
76
83
|
return Affine[ArrayT].translation(self.translation)
|
|
77
84
|
|
|
@@ -140,3 +147,7 @@ class Scale(Transform[ArrayT]):
|
|
|
140
147
|
|
|
141
148
|
def __str__(self) -> str:
|
|
142
149
|
return f"{super().__str__()}({join_strs(self.scale)})"
|
|
150
|
+
|
|
151
|
+
def is_identity(self) -> bool:
|
|
152
|
+
xp = array_namespace(self.scale)
|
|
153
|
+
return xp.all(self.scale == 1)
|
|
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
|