Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
nam
ProxPython
Commits
64fafb5d
Commit
64fafb5d
authored
Jun 17, 2016
by
Matthew Tam
Browse files
added the 1PTQ datafile and a Procrustes analysis utility function.
parent
f3a2e11f
Changes
2
Hide whitespace changes
Inline
Side-by-side
proxtoolbox/Utilities/Procrustes.py
0 → 100755
View file @
64fafb5d
import
numpy
as
np
def
procrustes
(
X
,
Y
,
scaling
=
True
,
reflection
=
'best'
):
"""
A port of MATLAB's `procrustes` function to Numpy.
Procrustes analysis determines a linear transformation (translation,
reflection, orthogonal rotation and scaling) of the points in Y to best
conform them to the points in matrix X, using the sum of squared errors
as the goodness of fit criterion.
d, Z, [tform] = procrustes(X, Y)
Inputs:
------------
X, Y
matrices of target and input coordinates. they must have equal
numbers of points (rows), but Y may have fewer dimensions
(columns) than X.
scaling
if False, the scaling component of the transformation is forced
to 1
reflection
if 'best' (default), the transformation solution may or may not
include a reflection component, depending on which fits the data
best. setting reflection to True or False forces a solution with
reflection or no reflection respectively.
Outputs
------------
d
the residual sum of squared errors, normalized according to a
measure of the scale of X, ((X - X.mean(0))**2).sum()
Z
the matrix of transformed Y-values
tform
a dict specifying the rotation, translation and scaling that
maps X --> Y
"""
n
,
m
=
X
.
shape
ny
,
my
=
Y
.
shape
muX
=
X
.
mean
(
0
)
muY
=
Y
.
mean
(
0
)
X0
=
X
-
muX
Y0
=
Y
-
muY
ssX
=
np
.
linalg
.
norm
(
X0
,
'fro'
)
**
2
#(X0**2.).sum()
ssY
=
np
.
linalg
.
norm
(
Y0
,
'fro'
)
**
2
#(Y0**2.).sum()
# centred Frobenius norm
normX
=
np
.
sqrt
(
ssX
)
normY
=
np
.
sqrt
(
ssY
)
# scale to equal (unit) norm
X0
/=
normX
Y0
/=
normY
if
my
<
m
:
Y0
=
np
.
concatenate
((
Y0
,
np
.
zeros
(
n
,
m
-
my
)),
0
)
# optimum rotation matrix of Y
A
=
np
.
dot
(
X0
.
T
,
Y0
)
U
,
s
,
Vt
=
np
.
linalg
.
svd
(
A
,
full_matrices
=
False
)
V
=
Vt
.
T
T
=
np
.
dot
(
V
,
U
.
T
)
if
reflection
is
not
'best'
:
# does the current solution use a reflection?
have_reflection
=
np
.
linalg
.
det
(
T
)
<
0
# if that's not what was specified, force another reflection
if
reflection
!=
have_reflection
:
V
[:,
-
1
]
*=
-
1
s
[
-
1
]
*=
-
1
T
=
np
.
dot
(
V
,
U
.
T
)
traceTA
=
s
.
sum
()
if
scaling
:
# optimum scaling of Y
b
=
traceTA
*
normX
/
normY
# standarised distance between X and b*Y*T + c
d
=
1
-
traceTA
**
2
# transformed coords
Z
=
normX
*
traceTA
*
np
.
dot
(
Y0
,
T
)
+
muX
else
:
b
=
1
d
=
1
+
ssY
/
ssX
-
2
*
traceTA
*
normY
/
normX
Z
=
normY
*
np
.
dot
(
Y0
,
T
)
+
muX
# transformation matrix
if
my
<
m
:
T
=
T
[:
my
,:]
c
=
muX
-
b
*
np
.
dot
(
muY
,
T
)
tform
=
{
'rotation'
:
T
,
'scale'
:
b
,
'translation'
:
c
}
return
d
,
Z
,
tform
proxtoolbox/Utilities/__init__.py
View file @
64fafb5d
...
...
@@ -8,5 +8,6 @@ The "Utilities"-module contains various ...
"""
from
.Laplace_matrix
import
*
from
.Procrustes
import
*
__all__
=
[
"Laplace_matrix"
]
__all__
=
[
"Laplace_matrix"
,
"procrustes"
]
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment