Generalized Procrustes analysis from TPS file#
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.decomposition import PCA
from ktch.landmark import GeneralizedProcrustesAnalysis
from ktch.io import read_tps
Reading TPS file#
df_triangles = read_tps("./landmarks_triangle.tps", as_frame=True)
df_triangles
x | y | ||
---|---|---|---|
specimen_id | coord_id | ||
0 | 0 | -0.531046 | -0.280265 |
1 | -0.177303 | 1.107969 | |
2 | 0.850131 | 1.064210 | |
1 | 0 | -0.480121 | -0.145592 |
1 | -0.172134 | 0.871833 | |
... | ... | ... | ... |
48 | 1 | -0.153270 | 0.980145 |
2 | 0.692266 | 0.797412 | |
49 | 0 | 0.286409 | -0.353412 |
1 | 0.213187 | 0.819529 | |
2 | 0.905297 | 1.175739 |
150 rows × 2 columns
fig, ax = plt.subplots()
sns.scatterplot(
data = df_triangles,
x="x",y="y",
hue="specimen_id", style="coord_id",ax=ax
)
ax.set_aspect('equal')
ax.legend(loc="upper left", bbox_to_anchor=(1, 1))
<matplotlib.legend.Legend at 0x7fb383f65510>
GPA#
gpa = GeneralizedProcrustesAnalysis().set_output(transform="pandas")
df_coords = df_triangles.unstack().swaplevel(1, 0, axis=1).sort_index(axis=1)
df_coords.columns = [dim +"_"+ str(landmark_idx) for landmark_idx,dim in df_coords.columns]
df_coords
df_shapes = gpa.fit_transform(df_coords)
df_shapes
x_0 | y_0 | x_1 | y_1 | x_2 | y_2 | |
---|---|---|---|---|---|---|
specimen_id | ||||||
0 | -0.308597 | -0.638893 | -0.182918 | 0.294741 | 0.491515 | 0.344152 |
1 | -0.372170 | -0.487439 | -0.196930 | 0.072799 | 0.569100 | 0.414639 |
10 | -0.397810 | -0.561799 | -0.035105 | 0.124281 | 0.432915 | 0.437517 |
11 | -0.373001 | -0.613285 | -0.047049 | 0.202706 | 0.420049 | 0.410578 |
12 | -0.252883 | -0.620455 | -0.273924 | 0.334570 | 0.526807 | 0.285885 |
13 | -0.254776 | -0.594599 | -0.302713 | 0.305677 | 0.557490 | 0.288922 |
14 | -0.382938 | -0.569850 | 0.082585 | 0.152466 | 0.300353 | 0.417384 |
15 | -0.219379 | -0.552450 | -0.364963 | 0.300367 | 0.584341 | 0.252083 |
16 | -0.320254 | -0.494104 | -0.293554 | 0.133409 | 0.613809 | 0.360695 |
17 | -0.339839 | -0.603099 | -0.181722 | 0.224615 | 0.521561 | 0.378484 |
18 | -0.164834 | -0.213849 | -0.460238 | 0.018214 | 0.625072 | 0.195635 |
19 | -0.210419 | -0.539588 | -0.379704 | 0.296860 | 0.590123 | 0.242728 |
2 | -0.366470 | -0.605654 | -0.106607 | 0.200327 | 0.473077 | 0.405327 |
20 | -0.258137 | -0.504275 | -0.364340 | 0.209567 | 0.622478 | 0.294708 |
21 | -0.277779 | -0.566517 | -0.306550 | 0.252162 | 0.584329 | 0.314355 |
22 | -0.225383 | -0.676497 | -0.160397 | 0.424545 | 0.385780 | 0.251952 |
23 | -0.258136 | -0.676376 | -0.146729 | 0.388877 | 0.404865 | 0.287499 |
24 | -0.280657 | -0.525423 | -0.330598 | 0.207082 | 0.611255 | 0.318341 |
25 | -0.215283 | -0.505609 | -0.397859 | 0.256911 | 0.613142 | 0.248698 |
26 | -0.298488 | -0.529990 | -0.307053 | 0.192821 | 0.605542 | 0.337170 |
27 | -0.278208 | -0.639379 | -0.222520 | 0.327345 | 0.500728 | 0.312034 |
28 | -0.279793 | -0.576087 | -0.296568 | 0.259852 | 0.576362 | 0.316235 |
29 | -0.338916 | -0.453648 | -0.273892 | 0.073030 | 0.612808 | 0.380618 |
3 | -0.322704 | -0.611777 | -0.202289 | 0.251470 | 0.524992 | 0.360307 |
30 | -0.274640 | -0.499224 | -0.349921 | 0.186841 | 0.624561 | 0.312383 |
31 | -0.298390 | -0.477677 | -0.329797 | 0.139820 | 0.628186 | 0.337857 |
32 | -0.176230 | -0.605882 | -0.325374 | 0.402546 | 0.501605 | 0.203336 |
33 | -0.172471 | -0.478251 | -0.435125 | 0.275359 | 0.607597 | 0.202892 |
34 | -0.210237 | -0.662379 | -0.213822 | 0.425334 | 0.424059 | 0.237045 |
35 | -0.361559 | -0.629282 | -0.000719 | 0.232784 | 0.362278 | 0.396499 |
36 | -0.325999 | -0.656920 | -0.093643 | 0.296540 | 0.419643 | 0.360380 |
37 | -0.219459 | -0.656613 | -0.228236 | 0.408965 | 0.447695 | 0.247648 |
38 | -0.215290 | -0.490939 | -0.405274 | 0.241976 | 0.620563 | 0.248962 |
39 | -0.191609 | -0.543643 | -0.385955 | 0.321385 | 0.577564 | 0.222258 |
4 | -0.305071 | -0.667015 | -0.110763 | 0.329092 | 0.415834 | 0.337923 |
40 | -0.180713 | -0.544016 | -0.389828 | 0.333606 | 0.570541 | 0.210410 |
41 | -0.292477 | -0.527482 | -0.315848 | 0.196632 | 0.608325 | 0.330850 |
42 | -0.339789 | -0.505137 | -0.257395 | 0.124155 | 0.597184 | 0.380983 |
43 | -0.280431 | -0.667834 | -0.154254 | 0.355587 | 0.434685 | 0.312248 |
44 | -0.152249 | -0.556962 | -0.384447 | 0.378016 | 0.536697 | 0.178947 |
45 | -0.188147 | -0.585896 | -0.348036 | 0.368714 | 0.536182 | 0.217182 |
46 | -0.097869 | -0.420238 | -0.481151 | 0.297762 | 0.579020 | 0.122476 |
47 | -0.143479 | -0.576299 | -0.363282 | 0.407693 | 0.506761 | 0.168606 |
48 | -0.085238 | -0.549413 | -0.377233 | 0.444315 | 0.462472 | 0.105097 |
49 | -0.337442 | -0.635403 | -0.130729 | 0.261232 | 0.468171 | 0.374171 |
5 | -0.272869 | -0.612984 | -0.265899 | 0.305389 | 0.538768 | 0.307596 |
6 | -0.318659 | -0.540386 | -0.273455 | 0.182147 | 0.592114 | 0.358240 |
7 | -0.302466 | -0.635791 | -0.197977 | 0.297888 | 0.500443 | 0.337903 |
8 | -0.231475 | -0.657097 | -0.223183 | 0.396410 | 0.454658 | 0.260687 |
9 | -0.162853 | -0.625506 | -0.292329 | 0.437954 | 0.455182 | 0.187552 |
df_shapes_vis = df_shapes.copy()
df_shapes_vis.columns = pd.MultiIndex.from_tuples([[int(landmark_idx), dim] for dim, landmark_idx in [idx.split("_") for idx in df_shapes_vis.columns]], names=["coord_id","dim"])
df_shapes_vis.sort_index(axis=1, inplace=True)
df_shapes_vis = df_shapes_vis.swaplevel(0,1,axis=1).stack(level=1)
df_shapes_vis
/tmp/ipykernel_1968/3231015902.py:4: FutureWarning: The previous implementation of stack is deprecated and will be removed in a future version of pandas. See the What's New notes for pandas 2.1.0 for details. Specify future_stack=True to adopt the new implementation and silence this warning.
df_shapes_vis = df_shapes_vis.swaplevel(0,1,axis=1).stack(level=1)
dim | x | y | |
---|---|---|---|
specimen_id | coord_id | ||
0 | 0 | -0.308597 | -0.638893 |
1 | -0.182918 | 0.294741 | |
2 | 0.491515 | 0.344152 | |
1 | 0 | -0.372170 | -0.487439 |
1 | -0.196930 | 0.072799 | |
... | ... | ... | ... |
8 | 1 | -0.223183 | 0.396410 |
2 | 0.454658 | 0.260687 | |
9 | 0 | -0.162853 | -0.625506 |
1 | -0.292329 | 0.437954 | |
2 | 0.455182 | 0.187552 |
150 rows × 2 columns
fig, ax = plt.subplots()
sns.scatterplot(
data = df_shapes_vis,
x="x",y="y",
hue="specimen_id", style="coord_id",ax=ax
)
ax.set_aspect('equal')
ax.legend(loc="upper left", bbox_to_anchor=(1, 1))
<matplotlib.legend.Legend at 0x7fb38097c490>