Spherical Harmonic (SPHARM) Analysis#
import numpy as np
import plotly.graph_objects as go
import vtk
from vtk.numpy_interface import dataset_adapter as dsa
from ktch.harmonic import SphericalHarmonicAnalysis, xyz2spherical
from ktch.datasets import fetch
Load 3D potato surface data#
# parameter mesh
para_path = fetch("danshaku_08_allSegments_para.vtp")
print(para_path)
reader = vtk.vtkXMLPolyDataReader()
reader.SetFileName(para_path)
reader.Update()
obj_para = dsa.WrapDataObject(reader.GetOutput())
# surface mesh
surf_path = fetch("danshaku_08_allSegments_surf.vtp")
print(surf_path)
reader = vtk.vtkXMLPolyDataReader()
reader.SetFileName(surf_path)
reader.Update()
obj_surf = dsa.WrapDataObject(reader.GetOutput())
Downloading data from 'https://pub-c1d6dba6c94843f88f0fd096d19c0831.r2.dev/examples/danshaku_08_allSegments_para/v1/danshaku_08_allSegments_para.vtp' to file '/home/runner/.cache/ktch-examples/danshaku_08_allSegments_para/v1/danshaku_08_allSegments_para.vtp'.
Downloading data from 'https://pub-c1d6dba6c94843f88f0fd096d19c0831.r2.dev/examples/danshaku_08_allSegments_surf/v1/danshaku_08_allSegments_surf.vtp' to file '/home/runner/.cache/ktch-examples/danshaku_08_allSegments_surf/v1/danshaku_08_allSegments_surf.vtp'.
/home/runner/.cache/ktch-examples/danshaku_08_allSegments_para/v1/danshaku_08_allSegments_para.vtp
/home/runner/.cache/ktch-examples/danshaku_08_allSegments_surf/v1/danshaku_08_allSegments_surf.vtp
arr_para_faces = np.array(obj_para.Polygons.reshape(-1, 4)[:, 1:])
arr_para = np.array(obj_para.Points)
arr_surf_faces = np.array(obj_surf.Polygons.reshape(-1, 4)[:, 1:])
arr_surf = np.array(obj_surf.Points)
Parameter mesh#
I, J, K = arr_para_faces.T
x_surf, y_surf, z_surf = arr_para.T
fig = go.Figure(
data=[
go.Mesh3d(
x=x_surf,
y=y_surf,
z=z_surf,
i=I,
j=J,
k=K,
opacity=0.3,
showscale=False,
),
]
)
fig.update_layout(
width=700,
height=700,
autosize=False,
scene=dict(
camera=dict(
up=dict(x=0, y=0, z=1),
eye=dict(
x=1.1,
y=1.1,
z=1.1,
),
),
aspectmode="data",
),
)
fig.show()
Surface mesh#
I, J, K = arr_surf_faces.T
x_surf, y_surf, z_surf = arr_surf.T
fig = go.Figure(
data=[
go.Mesh3d(
x=x_surf,
y=y_surf,
z=z_surf,
i=I,
j=J,
k=K,
opacity=0.3,
showscale=False,
),
]
)
fig.update_layout(
width=700,
height=700,
autosize=False,
scene=dict(
camera=dict(
up=dict(x=0, y=0, z=1),
eye=dict(
x=1.1,
y=1.1,
z=1.1,
),
),
aspectmode="data",
),
)
fig.show()
SPHARM Analysis#
# registration=None keeps raw coefficients for overlaying the original
spharm_analysis = SphericalHarmonicAnalysis(n_harmonics=10, registration=None)
X_transform = spharm_analysis.fit_transform([arr_surf], theta_phi=[xyz2spherical(arr_para)])
X_transform
array([[-2.29720027e-02, 2.48897304e-03, 1.10721107e-02,
6.58749779e-02, -1.88412734e-03, -9.04224781e-04,
-2.13759708e-04, -3.48942456e-03, 1.14882134e-03,
8.96017561e-04, 7.86471053e-04, -4.42645167e-04,
-3.46744938e-04, 3.24924542e-04, 9.91263876e-04,
-1.96090710e-04, -7.51414278e-04, -2.44784493e-04,
4.44948637e-04, -1.12307089e-04, 2.26480964e-04,
5.49308696e-04, -5.92964990e-04, -3.68909955e-04,
-7.16184973e-04, 2.02576834e-04, -6.69970335e-04,
-1.32382554e-05, 1.73828493e-04, -9.36413122e-05,
-2.94812777e-04, 1.03155813e-03, 2.63623316e-04,
-5.80006553e-04, 1.01434621e-04, -8.53467144e-05,
3.10549497e-05, 1.14528701e-04, 5.37492309e-04,
-9.91803204e-06, 2.00438759e-04, 8.49202351e-05,
4.95629142e-05, 3.85075995e-04, 7.98221903e-06,
2.56847860e-04, 8.43472146e-06, -6.29500969e-04,
-3.00995314e-04, 7.15585967e-05, -1.84407996e-04,
-6.79017227e-05, 4.82502311e-05, 1.04724513e-06,
4.32939597e-05, 1.01194979e-04, 3.30894007e-06,
-1.10895391e-04, -5.50610245e-06, 2.64687825e-04,
-1.07519805e-04, -4.30962761e-04, -2.90266659e-05,
5.10077068e-05, -9.54234291e-05, -3.00744005e-05,
-1.92703592e-04, -1.39380614e-04, 1.70239136e-04,
1.55171296e-04, -2.37209145e-05, 4.18032798e-05,
-3.38266971e-05, -1.47348368e-04, -1.98609686e-05,
7.05419405e-05, 1.60770405e-05, -2.90684437e-05,
5.63951743e-05, 1.26833550e-04, -1.32156558e-06,
1.41823926e-04, 5.59827973e-05, 3.07812697e-06,
1.09042345e-04, -8.76469278e-06, -1.32338314e-05,
2.44472379e-05, -3.15469824e-05, -9.82420955e-08,
-9.65559513e-05, 5.18039472e-05, 4.19000835e-05,
-1.26956043e-04, 6.35386336e-05, 1.08406674e-04,
-8.52131849e-05, -1.00843307e-04, -1.27415118e-04,
-2.72490612e-05, -8.18066921e-05, -2.18691950e-05,
-1.80777200e-05, -7.16985558e-05, -7.77004158e-05,
4.37230935e-05, -5.84898393e-05, -1.86098189e-05,
-2.87965955e-05, -2.25188800e-05, -6.33736365e-05,
1.65206414e-04, 2.65670624e-05, -6.58327392e-05,
6.82958374e-05, 2.07534080e-05, -1.14730893e-04,
-1.78375524e-05, 2.24814402e-05, -1.72531310e-05,
-5.68174308e-05, 1.20166975e-01, -4.57018843e-02,
-2.92836043e-02, -1.78043164e-03, 2.08948471e-04,
1.17996547e-03, 4.58999544e-04, 6.39358863e-05,
1.08406660e-03, -2.43563368e-03, 6.71051667e-05,
-6.00420500e-04, 6.45703929e-05, 8.20336199e-05,
3.22800241e-04, 4.98165661e-04, -1.26058583e-03,
-1.02549120e-03, 1.29034834e-04, -1.08432118e-04,
8.58986023e-05, 2.80544234e-04, -5.41581394e-04,
-4.04062229e-04, -5.52273317e-04, 2.07193783e-04,
-5.98608180e-04, -7.48400077e-04, -2.41370395e-04,
-1.10436122e-04, -7.51675152e-07, 1.38446358e-04,
-4.02500982e-04, -3.91873256e-04, 3.25145355e-04,
2.61207841e-04, 2.90791746e-04, 6.13732486e-04,
4.02343835e-04, -3.18754778e-04, 1.88883108e-05,
-5.38619118e-04, 1.61558991e-04, -1.07760761e-04,
-2.59938630e-04, -2.28925080e-05, 3.48788582e-04,
8.19315907e-06, -9.31128566e-06, -1.06410460e-04,
-5.04272359e-05, 3.47659741e-04, -2.84962033e-05,
-1.59913933e-05, 1.76309121e-04, -2.37360866e-04,
4.02438946e-05, -1.45095587e-04, -9.18538718e-05,
-1.03949479e-04, 1.21149922e-04, 1.97081804e-04,
-1.18255378e-04, -6.77488064e-05, -7.69819411e-05,
5.34471947e-05, 2.21896005e-04, 3.02359696e-05,
-4.62163288e-05, 5.17774373e-05, -2.07755947e-05,
3.16721371e-05, 3.91490893e-05, -7.92975695e-05,
2.26871935e-04, -1.71638835e-05, 1.86382932e-04,
2.33975426e-04, 2.41957956e-04, -8.93480487e-05,
-8.02988024e-05, 1.01039714e-04, -1.35621382e-04,
1.13120618e-05, 7.80795414e-05, -7.84740513e-06,
-6.50121008e-05, 9.39321789e-05, 3.58260258e-06,
-3.36738138e-06, -1.16021165e-04, 1.09754140e-04,
5.83097980e-05, 7.76786498e-08, 2.95108811e-05,
1.66244407e-04, -1.59354825e-04, -2.87446637e-04,
1.87457033e-05, 2.14879352e-04, -4.45393499e-05,
-1.62349775e-06, -7.54175011e-05, -1.76685944e-04,
2.70132123e-05, -6.85878461e-05, -1.98475976e-05,
-2.33349650e-05, -9.86704484e-06, -4.99731993e-05,
-3.00361106e-05, -1.51402328e-05, -1.26094442e-05,
3.11205234e-05, -1.04432494e-05, 1.86333550e-05,
-1.26776860e-04, -9.79741822e-05, 4.12407682e-05,
-1.98544548e-06, -7.91947451e-05, -1.15047627e+00,
1.48890454e-02, -4.76763240e-02, 1.90055413e-03,
-3.25398264e-05, -1.71732166e-03, -2.83188383e-03,
3.97352546e-05, -9.23357246e-04, 1.16393903e-03,
2.99497005e-04, -2.07685095e-03, -1.95999274e-03,
-1.79953941e-03, -1.66321353e-03, 7.48336429e-05,
4.61072613e-04, 2.51663467e-04, 4.04768265e-04,
2.05540897e-05, -1.23425224e-03, 2.33905522e-04,
1.59711414e-04, -8.63769623e-05, 7.56225175e-04,
-1.16425725e-04, 3.57394216e-05, -8.97827354e-05,
2.08667657e-04, 2.49988835e-04, -2.23306849e-04,
4.02295907e-04, -2.86371155e-05, -2.39005411e-04,
3.29830524e-04, 8.69183641e-05, -2.99695949e-04,
-2.31110648e-04, -1.28784762e-04, -4.85688334e-04,
-7.46369518e-05, 7.29466621e-05, 4.07137730e-05,
-1.79749824e-04, -4.04248303e-04, 8.70209521e-05,
2.54030933e-04, 1.97306835e-04, -1.82018586e-04,
1.45122607e-04, -1.31216509e-05, -4.43416471e-05,
-1.98245898e-04, -7.64532072e-05, -1.27541230e-04,
1.71050350e-04, 1.05310610e-04, 5.84795493e-05,
-1.26664207e-04, 6.20618582e-05, 1.79014061e-04,
-1.06013531e-04, 1.29491550e-04, 5.15163332e-05,
1.67682121e-05, 3.95248569e-05, 1.85547158e-04,
-1.89267181e-05, -1.34466788e-05, -1.37260778e-04,
-5.84829352e-05, -2.40626995e-04, 3.29445676e-06,
-6.93285477e-05, 1.20621523e-04, -9.37505878e-05,
-1.87627867e-04, 3.80125525e-05, -7.76577248e-05,
5.22594276e-06, 4.15875714e-05, -6.35006408e-05,
-1.06864066e-04, -8.62110099e-05, 1.62823793e-04,
1.84039405e-04, -1.67959236e-05, 7.14654699e-06,
9.98701973e-06, -6.99501840e-05, -1.04087657e-04,
1.60687940e-05, 2.56547311e-04, -1.29621254e-04,
-2.21146572e-04, 2.63752340e-05, -2.88686528e-05,
1.06601973e-04, 6.10283164e-05, -7.49353072e-05,
3.81499270e-05, 2.47948386e-05, 5.01497815e-05,
4.89607757e-05, 8.87421186e-05, 8.50700799e-05,
-5.30953817e-05, 1.41718381e-04, 5.90517896e-05,
7.53406540e-05, -4.48072503e-05, -4.42725296e-05,
1.17121933e-04, 1.63044796e-05, -2.05474907e-05,
-8.24987960e-05, -6.62420519e-05, 3.30956844e-05,
9.80959843e-05, 6.17558737e-05, 4.57492333e-05]])
Inverse analysis#
Reconstruct 3D surface shapes from SPHARM coefficients.
X_coords = spharm_analysis.inverse_transform(X_transform.reshape(1, 3, -1))
x_sph, y_sph, z_sph = X_coords[0].T
fig = go.Figure(
data=[
go.Surface(
x=x_sph,
y=y_sph,
z=z_sph,
opacity=0.3,
showscale=False,
),
]
)
fig.update_layout(
width=700,
height=700,
autosize=False,
scene=dict(
camera=dict(
up=dict(x=0, y=0, z=1),
eye=dict(
x=1.1,
y=1.1,
z=1.1,
),
),
aspectmode="data",
),
)
fig.show()
Original vs reconstructed shapes#
Overlay the original and reconstructed surface data. This demonstrates that the original shape is well reproduced.
I, J, K = arr_surf_faces.T
x_surf, y_surf, z_surf = arr_surf.T
x_sph, y_sph, z_sph = X_coords[0].T
fig = go.Figure(
data=[
go.Mesh3d(
x=x_surf,
y=y_surf,
z=z_surf,
i=I,
j=J,
k=K,
opacity=0.8,
showscale=False,
),
go.Surface(
x=x_sph,
y=y_sph,
z=z_sph,
opacity=0.4,
showscale=False,
),
]
)
fig.update_layout(
width=700,
height=700,
autosize=False,
scene=dict(
camera=dict(
up=dict(x=0, y=0, z=1),
eye=dict(
x=1.1,
y=1.1,
z=1.1,
),
),
aspectmode="data",
),
)
fig.show()