forked from AllenInstitute/render-python
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathutils.py
More file actions
92 lines (84 loc) · 3.5 KB
/
utils.py
File metadata and controls
92 lines (84 loc) · 3.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
from collections.abc import Iterable
from renderapi.errors import RenderError
from .leaf import AffineModel, Polynomial2DTransform
from .transform import TransformList, ReferenceTransform
__all__ = ['estimate_dstpts',
'estimate_transformsum']
def estimate_dstpts(transformlist, src=None, reference_tforms=None):
"""estimate destination points for list of transforms. Recurses
through lists.
Parameters
----------
transformlist : :obj:list of :obj:Transform
transforms that have a tform method implemented
src : numpy.array
a Nx2 array of source points
Returns
-------
numpy.array
Nx2 array of destination points
"""
dstpts = src
for tform in transformlist:
if isinstance(tform, list):
dstpts = estimate_dstpts(tform, dstpts, reference_tforms)
elif isinstance(tform, TransformList):
dstpts = estimate_dstpts(tform.tforms, dstpts, reference_tforms)
elif isinstance(tform, ReferenceTransform):
try:
tform_deref = next((tf for tf in reference_tforms
if tf.transformId == tform.refId))
except TypeError:
raise RenderError(
"you supplied a set of tranforms that includes a "
"reference transform, but didn't supply a set of "
"reference transforms to enable dereferencing")
except StopIteration:
raise RenderError(
"the list of transforms you provided references "
"transorm {} but that transform could not be found "
"in the list of reference transforms".format(tform.refId))
dstpts = estimate_dstpts([tform_deref], dstpts, reference_tforms)
else:
dstpts = tform.tform(dstpts)
return dstpts
def estimate_transformsum(transformlist, src=None, order=2):
"""pseudo-composition of transforms in list of transforms
using source point transformation and a single estimation.
Will produce an Affine Model if all input transforms are Affine,
otherwise will produce a Polynomial of specified order
Parameters
----------
transformlist : :obj:`list` of :obj:`Transform`
list of transform objects that implement tform
src : numpy.array
Nx2 array of source points for estimation
order : int
order of Polynomial output if transformlist
inputs are non-Affine
Returns
-------
:class:`AffineModel` or :class:`Polynomial2DTransform`
best estimate of transformlist in a single transform of this order
"""
def flatten(l):
"""generator-iterator to flatten deep lists of lists"""
for i in l:
if isinstance(i, Iterable):
try:
notstring = isinstance(i, basestring)
except NameError:
notstring = isinstance(i, str)
if notstring:
for sub in flatten(i):
yield sub
else:
yield i
dstpts = estimate_dstpts(transformlist, src)
tforms = flatten(transformlist)
if all([(tform.className == AffineModel.className)
for tform in tforms]):
am = AffineModel()
am.estimate(A=src, B=dstpts, return_params=False)
return am
return Polynomial2DTransform(src=src, dst=dstpts, order=order)