LDDMM with normalized kernel

This notebook illustrates the interest of normalizing the cometric in the LDDMM model. We consider the registration of two spheres that differ by a translation first, and then a more complex registration task with a translation and a deformation.

Without normalization, the carpooling artifact occurs: the sphere is contracted, then translated and finally expanded. in this situation, event if the morphed shape matches the target, the intermediate shapes are not meaningful and the extrapolation is not reliable.

Normalizing the kernel adds regularization to the morphing, leanding to prevention of the carpooling artifact and improvement of the extrapolation to some extent.

Options for normalization are:

Further explanation can be found in the p177 and onwards of https://www.jeanfeydy.com/geometric_data_analysis.pdf.

from time import time

import pyvista as pv
import torch

import skshapes as sks

# sphinx_gallery_thumbnail_number = 9

Load data

plot_kwargs = {
    "smooth_shading": True,
    "pbr": True,
    "metallic": 0.7,
    "roughness": 0.6,

}

cpos = [(1.6256104086078755, -9.701422233882411, 1.3012755902068773),
 (1.191160019984921, 0.01901107976782581, -0.0052552929581526076),
 (0.006053690112347382, 0.13347614338229413, 0.9910335372649167)]

source = sks.Sphere()
target = sks.Sphere()

decimation = sks.Decimation(n_points = 200)
source = decimation.fit_transform(source)
target = decimation.transform(target)

target.points = target.points + torch.tensor([2, 0.0, 0.0])

plotter = pv.Plotter()
plotter.add_mesh(source.to_pyvista(), color="teal", opacity=0.8, **plot_kwargs)
plotter.add_mesh(target.to_pyvista(), color="red", opacity=0.8, **plot_kwargs)
plotter.camera_position = cpos
plotter.show()
plot lddmm 1 normalization

LDDM without normalization

model = sks.ExtrinsicDeformation(
    n_steps=4,
    kernel="gaussian",
    scale=0.3,
)

loss = sks.L2Loss()

task = sks.Registration(
    model=model,
    loss=loss,
    optimizer=sks.LBFGS(),
    n_iter=3,
    regularization_weight=1e-1,
    verbose=True,
)

start = time()
task.fit(source=source, target=target)
print("Elapsed time: ", time() - start)
path = task.path_

plotter = pv.Plotter()
plotter.add_mesh(source.to_pyvista(), color="teal", opacity=0.2, **plot_kwargs)
plotter.add_mesh(target.to_pyvista(), color="red", opacity=0.2, **plot_kwargs)
for i in range(len(path)):
    plotter.add_mesh(path[i].to_pyvista(), color="tan", opacity=0.8, **plot_kwargs)
plotter.camera_position = cpos
plotter.show()
plot lddmm 1 normalization
[KeOps] Generating code for Sum_Reduction reduction (with parameters 0) of formula Exp(-Sum((a-b)**2))*c with a=Var(0,3,0), b=Var(1,3,1), c=Var(2,3,1) ... OK
[pyKeOps] Compiling pykeops cpp 53d8b63c4c module ... OK
[KeOps] Generating code for Sum_Reduction reduction (with parameters 0) of formula (-2*((a-b)*(d|c)))*Exp(-Sum((a-b)**2)) with a=Var(0,3,0), b=Var(1,3,1), c=Var(2,3,1), d=Var(3,3,0) ... OK
[pyKeOps] Compiling pykeops cpp 42d1c2bb84 module ... OK
[KeOps] Generating code for Sum_Reduction reduction (with parameters 1) of formula (2*((a-b)*(d|c)))*Exp(-Sum((a-b)**2)) with a=Var(0,3,0), b=Var(1,3,1), c=Var(2,3,1), d=Var(3,3,0) ... OK
[pyKeOps] Compiling pykeops cpp 90af7935d4 module ... OK
[KeOps] Generating code for Sum_Reduction reduction (with parameters 1) of formula Exp(-Sum((a-b)**2))*d with a=Var(0,3,0), b=Var(1,3,1), d=Var(3,3,0) ... OK
[pyKeOps] Compiling pykeops cpp d78b822b9e module ... OK
Initial loss : 2.84e+01
  = 2.84e+01 + 0.1 * 0.00e+00 (fidelity + regularization_weight * regularization)
[KeOps] Generating code for Sum_Reduction reduction (with parameters 0) of formula (-2*((a-b)*(f|d)))*Exp(-Sum((a-b)**2)) with a=Var(0,3,0), b=Var(1,3,1), d=Var(3,3,0), f=Var(5,3,1) ... OK
[pyKeOps] Compiling pykeops cpp 52e01d1132 module ... OK
[KeOps] Generating code for Sum_Reduction reduction (with parameters 1) of formula (2*((a-b)*(f|d)))*Exp(-Sum((a-b)**2)) with a=Var(0,3,0), b=Var(1,3,1), d=Var(3,3,0), f=Var(5,3,1) ... OK
[pyKeOps] Compiling pykeops cpp 5c72c5b452 module ... OK
[KeOps] Generating code for Sum_Reduction reduction (with parameters 1) of formula Zero(3) with  ... OK
[pyKeOps] Compiling pykeops cpp 6b9d40cb88 module ... OK
[KeOps] Generating code for Sum_Reduction reduction (with parameters 0) of formula Exp(-Sum((a-b)**2))*f with a=Var(0,3,0), b=Var(1,3,1), f=Var(5,3,1) ... OK
[pyKeOps] Compiling pykeops cpp e221bcfff3 module ... OK
[KeOps] Generating code for Sum_Reduction reduction (with parameters 0) of formula (2*((d|c)*f)+-4*((a-b)*((d|c)*((a-b)|f))))*Exp(-Sum((a-b)**2)) with a=Var(0,3,0), b=Var(1,3,1), c=Var(2,3,1), d=Var(3,3,0), f=Var(5,3,1) ... OK
[pyKeOps] Compiling pykeops cpp a44d3d3db5 module ... OK
[KeOps] Generating code for Sum_Reduction reduction (with parameters 1) of formula (-2*((d|c)*f)+4*((a-b)*((d|c)*((a-b)|f))))*Exp(-Sum((a-b)**2)) with a=Var(0,3,0), b=Var(1,3,1), c=Var(2,3,1), d=Var(3,3,0), f=Var(5,3,1) ... OK
[pyKeOps] Compiling pykeops cpp 369de12a48 module ... OK
[KeOps] Generating code for Sum_Reduction reduction (with parameters 1) of formula (2*((f|(a-b))*d))*Exp(-Sum((a-b)**2)) with a=Var(0,3,0), b=Var(1,3,1), d=Var(3,3,0), f=Var(5,3,1) ... OK
[pyKeOps] Compiling pykeops cpp 42e8032490 module ... OK
[KeOps] Generating code for Sum_Reduction reduction (with parameters 0) of formula (2*((f|(a-b))*c))*Exp(-Sum((a-b)**2)) with a=Var(0,3,0), b=Var(1,3,1), c=Var(2,3,1), f=Var(5,3,1) ... OK
[pyKeOps] Compiling pykeops cpp efcd299a74 module ... OK
[KeOps] Generating code for Sum_Reduction reduction (with parameters 0) of formula (-2*((d|c)*f)+4*((a-b)*((d|c)*((a-b)|f))))*Exp(-Sum((a-b)**2)) with a=Var(0,3,0), b=Var(1,3,1), c=Var(2,3,1), d=Var(3,3,0), f=Var(5,3,0) ... OK
[pyKeOps] Compiling pykeops cpp c1e554924b module ... OK
[KeOps] Generating code for Sum_Reduction reduction (with parameters 1) of formula (2*((d|c)*f)+-4*((a-b)*((d|c)*((a-b)|f))))*Exp(-Sum((a-b)**2)) with a=Var(0,3,0), b=Var(1,3,1), c=Var(2,3,1), d=Var(3,3,0), f=Var(5,3,0) ... OK
[pyKeOps] Compiling pykeops cpp 234f2ba8f2 module ... OK
[KeOps] Generating code for Sum_Reduction reduction (with parameters 1) of formula (-2*((f|(a-b))*d))*Exp(-Sum((a-b)**2)) with a=Var(0,3,0), b=Var(1,3,1), d=Var(3,3,0), f=Var(5,3,0) ... OK
[pyKeOps] Compiling pykeops cpp 0538180a79 module ... OK
[KeOps] Generating code for Sum_Reduction reduction (with parameters 0) of formula (-2*((f|(a-b))*c))*Exp(-Sum((a-b)**2)) with a=Var(0,3,0), b=Var(1,3,1), c=Var(2,3,1), f=Var(5,3,0) ... OK
[pyKeOps] Compiling pykeops cpp 2175ab1eb1 module ... OK
Loss after 1 iteration(s) : 1.83e+00
  = 1.42e+00 + 0.1 * 4.12e+00 (fidelity + regularization_weight * regularization)
Loss after 2 iteration(s) : 6.65e-01
  = 2.64e-01 + 0.1 * 4.01e+00 (fidelity + regularization_weight * regularization)
Loss after 3 iteration(s) : 5.96e-01
  = 1.96e-01 + 0.1 * 4.00e+00 (fidelity + regularization_weight * regularization)
Elapsed time:  67.24385094642639

Extrapolation

back = model.morph(
    shape=source,
    parameter=task.parameter_,
    final_time=-1.0,
    return_path=True,
).path

model.n_steps = 8
forward = model.morph(
    shape=source,
    parameter=task.parameter_,
    final_time=2.0,
    return_path=True,
).path

path = back[::-1] + forward[1:]

plotter = pv.Plotter()
plotter.open_gif("lddmm_no_normalization.gif", fps=4)
for i in range(len(path)):
    plotter.clear_actors()
    plotter.add_mesh(source.to_pyvista(), color="teal", opacity=0.2, **plot_kwargs)
    plotter.add_mesh(target.to_pyvista(), color="red", opacity=0.2, **plot_kwargs)
    plotter.add_mesh(path[i].to_pyvista(), color="tan", opacity=0.8, **plot_kwargs)
    plotter.camera_position = cpos
    plotter.write_frame()
plotter.close()
plot lddmm 1 normalization

Normalizing the rows of the kernel

model_norm = sks.ExtrinsicDeformation(
    n_steps=4,
    kernel="gaussian",
    scale=0.3,
    normalization="rows",
)

task_norm = sks.Registration(
    model=model_norm,
    loss=loss,
    optimizer=sks.LBFGS(),
    n_iter=1,
    regularization_weight=0.0,
    verbose=True,
)

start = time()
task_norm.fit(source=source, target=target)
print("Elapsed time: ", time() - start)
path = task_norm.path_

plotter = pv.Plotter()
plotter.add_mesh(source.to_pyvista(), color="teal", opacity=0.2, **plot_kwargs)
plotter.add_mesh(target.to_pyvista(), color="red", opacity=0.2, **plot_kwargs)
for i in range(len(path)):
    plotter.add_mesh(path[i].to_pyvista(), color="tan", opacity=0.8, **plot_kwargs)
plotter.camera_position = cpos
plotter.show()
plot lddmm 1 normalization
[KeOps] Generating code for Sum_Reduction reduction (with parameters 0) of formula Exp(-Sum((a-b)**2)) with a=Var(0,3,0), b=Var(1,3,1) ... OK
[pyKeOps] Compiling pykeops cpp 86d46fe1aa module ... OK
[KeOps] Generating code for Sum_Reduction reduction (with parameters 0) of formula (-2*((a-b)*c))*Exp(-Sum((a-b)**2)) with a=Var(0,3,0), b=Var(1,3,1), c=Var(2,1,0) ... OK
[pyKeOps] Compiling pykeops cpp 70dadc1e68 module ... OK
[KeOps] Generating code for Sum_Reduction reduction (with parameters 1) of formula (2*((a-b)*c))*Exp(-Sum((a-b)**2)) with a=Var(0,3,0), b=Var(1,3,1), c=Var(2,1,0) ... OK
[pyKeOps] Compiling pykeops cpp 889cb01593 module ... OK
Initial loss : 2.84e+01
  = 2.84e+01 + 0 (fidelity + regularization_weight * regularization)
[KeOps] Generating code for Sum_Reduction reduction (with parameters 0) of formula (2*(c*e)+-4*((a-b)*(c*((a-b)|e))))*Exp(-Sum((a-b)**2)) with a=Var(0,3,0), b=Var(1,3,1), c=Var(2,1,0), e=Var(4,3,1) ... OK
[pyKeOps] Compiling pykeops cpp 9098e59e88 module ... OK
[KeOps] Generating code for Sum_Reduction reduction (with parameters 1) of formula (-2*(c*e)+4*((a-b)*(c*((a-b)|e))))*Exp(-Sum((a-b)**2)) with a=Var(0,3,0), b=Var(1,3,1), c=Var(2,1,0), e=Var(4,3,1) ... OK
[pyKeOps] Compiling pykeops cpp 3668ec0b41 module ... OK
[KeOps] Generating code for Sum_Reduction reduction (with parameters 0) of formula (2*(e|(a-b)))*Exp(-Sum((a-b)**2)) with a=Var(0,3,0), b=Var(1,3,1), e=Var(4,3,1) ... OK
[pyKeOps] Compiling pykeops cpp 4751fc1a9e module ... OK
[KeOps] Generating code for Sum_Reduction reduction (with parameters 0) of formula (-2*(c*e)+4*((a-b)*(c*((a-b)|e))))*Exp(-Sum((a-b)**2)) with a=Var(0,3,0), b=Var(1,3,1), c=Var(2,1,0), e=Var(4,3,0) ... OK
[pyKeOps] Compiling pykeops cpp d3435b7e0b module ... OK
[KeOps] Generating code for Sum_Reduction reduction (with parameters 1) of formula (2*(c*e)+-4*((a-b)*(c*((a-b)|e))))*Exp(-Sum((a-b)**2)) with a=Var(0,3,0), b=Var(1,3,1), c=Var(2,1,0), e=Var(4,3,0) ... OK
[pyKeOps] Compiling pykeops cpp fc0560bc9d module ... OK
[KeOps] Generating code for Sum_Reduction reduction (with parameters 0) of formula (-2*(e|(a-b)))*Exp(-Sum((a-b)**2)) with a=Var(0,3,0), b=Var(1,3,1), e=Var(4,3,0) ... OK
[pyKeOps] Compiling pykeops cpp e703df3974 module ... OK
Loss after 1 iteration(s) : 5.40e-02
  = 5.40e-02 + 0 (fidelity + regularization_weight * regularization)
Elapsed time:  37.87876892089844

Extrapolation

back = model_norm.morph(
    shape=source,
    parameter=task_norm.parameter_,
    final_time=-1.0,
    return_path=True,
).path

model_norm.n_steps = 8
forward = model_norm.morph(
    shape=source,
    parameter=task_norm.parameter_,
    final_time=2.0,
    return_path=True,
).path

path = back[::-1] + forward[1:]

plotter = pv.Plotter()
plotter.open_gif("lddmm_normalization.gif", fps=4)
for i in range(len(path)):
    plotter.clear_actors()
    plotter.add_mesh(source.to_pyvista(), color="teal", opacity=0.2, **plot_kwargs)
    plotter.add_mesh(target.to_pyvista(), color="red", opacity=0.2, **plot_kwargs)
    plotter.add_mesh(path[i].to_pyvista(), color="tan", opacity=0.8, **plot_kwargs)
    plotter.camera_position = cpos
    plotter.write_frame()
plotter.close()
plot lddmm 1 normalization

Normalizing both rows and columns of the kernel

model_norm = sks.ExtrinsicDeformation(
    n_steps=4,
    kernel="gaussian",
    scale=0.3,
    normalization="both",
)

task_norm = sks.Registration(
    model=model_norm,
    loss=loss,
    optimizer=sks.LBFGS(),
    n_iter=1,
    regularization_weight=0.0,
    verbose=True,
)

start = time()
task_norm.fit(source=source, target=target)
elapsed_time = time() - start
path = task_norm.path_

plotter = pv.Plotter()
plotter.add_mesh(source.to_pyvista(), color="teal", opacity=0.2, **plot_kwargs)
plotter.add_mesh(target.to_pyvista(), color="red", opacity=0.2, **plot_kwargs)
for i in range(len(path)):
    plotter.add_mesh(path[i].to_pyvista(), color="tan", opacity=0.8, **plot_kwargs)
plotter.camera_position = cpos
plotter.show()
plot lddmm 1 normalization
[KeOps] Generating code for Sum_Reduction reduction (with parameters 0) of formula c*Exp(-Sum((a-b)**2)) with a=Var(0,3,0), b=Var(1,3,1), c=Var(2,1,1) ... OK
[pyKeOps] Compiling pykeops cpp 151acd82c2 module ... OK
[KeOps] Generating code for Sum_Reduction reduction (with parameters 0) of formula (-2*((a-b)*(d*c)))*Exp(-Sum((a-b)**2)) with a=Var(0,3,0), b=Var(1,3,1), c=Var(2,1,1), d=Var(3,1,0) ... OK
[pyKeOps] Compiling pykeops cpp f15387d04d module ... OK
[KeOps] Generating code for Sum_Reduction reduction (with parameters 1) of formula (2*((a-b)*(d*c)))*Exp(-Sum((a-b)**2)) with a=Var(0,3,0), b=Var(1,3,1), c=Var(2,1,1), d=Var(3,1,0) ... OK
[pyKeOps] Compiling pykeops cpp c505e5a190 module ... OK
[KeOps] Generating code for Sum_Reduction reduction (with parameters 1) of formula d*Exp(-Sum((a-b)**2)) with a=Var(0,3,0), b=Var(1,3,1), d=Var(3,1,0) ... OK
[pyKeOps] Compiling pykeops cpp bb78e072a3 module ... OK
Initial loss : 2.84e+01
  = 2.84e+01 + 0 (fidelity + regularization_weight * regularization)
[KeOps] Generating code for Sum_Reduction reduction (with parameters 0) of formula (2*((d*c)*f)+-4*((a-b)*((d*c)*((a-b)|f))))*Exp(-Sum((a-b)**2)) with a=Var(0,3,0), b=Var(1,3,1), c=Var(2,1,1), d=Var(3,1,0), f=Var(5,3,1) ... OK
[pyKeOps] Compiling pykeops cpp f7b5a73a8e module ... OK
[KeOps] Generating code for Sum_Reduction reduction (with parameters 1) of formula (-2*((d*c)*f)+4*((a-b)*((d*c)*((a-b)|f))))*Exp(-Sum((a-b)**2)) with a=Var(0,3,0), b=Var(1,3,1), c=Var(2,1,1), d=Var(3,1,0), f=Var(5,3,1) ... OK
[pyKeOps] Compiling pykeops cpp c59efd8557 module ... OK
[KeOps] Generating code for Sum_Reduction reduction (with parameters 0) of formula (2*(c*(f|(a-b))))*Exp(-Sum((a-b)**2)) with a=Var(0,3,0), b=Var(1,3,1), c=Var(2,1,1), f=Var(5,3,1) ... OK
[pyKeOps] Compiling pykeops cpp 5b9174a19f module ... OK
[KeOps] Generating code for Sum_Reduction reduction (with parameters 0) of formula (-2*((d*c)*f)+4*((a-b)*((d*c)*((a-b)|f))))*Exp(-Sum((a-b)**2)) with a=Var(0,3,0), b=Var(1,3,1), c=Var(2,1,1), d=Var(3,1,0), f=Var(5,3,0) ... OK
[pyKeOps] Compiling pykeops cpp 80bb359e65 module ... OK
[KeOps] Generating code for Sum_Reduction reduction (with parameters 1) of formula (2*((d*c)*f)+-4*((a-b)*((d*c)*((a-b)|f))))*Exp(-Sum((a-b)**2)) with a=Var(0,3,0), b=Var(1,3,1), c=Var(2,1,1), d=Var(3,1,0), f=Var(5,3,0) ... OK
[pyKeOps] Compiling pykeops cpp 72c5c4a9f3 module ... OK
[KeOps] Generating code for Sum_Reduction reduction (with parameters 0) of formula (-2*(c*(f|(a-b))))*Exp(-Sum((a-b)**2)) with a=Var(0,3,0), b=Var(1,3,1), c=Var(2,1,1), f=Var(5,3,0) ... OK
[pyKeOps] Compiling pykeops cpp 9bac215434 module ... OK
[KeOps] Generating code for Sum_Reduction reduction (with parameters 0) of formula (-2*((a-b)*(f*d)))*Exp(-Sum((a-b)**2)) with a=Var(0,3,0), b=Var(1,3,1), d=Var(3,1,0), f=Var(5,1,1) ... OK
[pyKeOps] Compiling pykeops cpp cd3eb7d2f1 module ... OK
[KeOps] Generating code for Sum_Reduction reduction (with parameters 1) of formula (2*((a-b)*(f*d)))*Exp(-Sum((a-b)**2)) with a=Var(0,3,0), b=Var(1,3,1), d=Var(3,1,0), f=Var(5,1,1) ... OK
[pyKeOps] Compiling pykeops cpp 4e195119f1 module ... OK
[KeOps] Generating code for Sum_Reduction reduction (with parameters 1) of formula Zero(1) with  ... OK
[pyKeOps] Compiling pykeops cpp 5c239a6aa2 module ... OK
[KeOps] Generating code for Sum_Reduction reduction (with parameters 0) of formula f*Exp(-Sum((a-b)**2)) with a=Var(0,3,0), b=Var(1,3,1), f=Var(5,1,1) ... OK
[pyKeOps] Compiling pykeops cpp a097c2198e module ... OK
[KeOps] Generating code for Sum_Reduction reduction (with parameters 1) of formula (2*(d*(f|(a-b))))*Exp(-Sum((a-b)**2)) with a=Var(0,3,0), b=Var(1,3,1), d=Var(3,1,0), f=Var(5,3,1) ... OK
[pyKeOps] Compiling pykeops cpp 10c2b19683 module ... OK
[KeOps] Generating code for Sum_Reduction reduction (with parameters 1) of formula (-2*(d*(f|(a-b))))*Exp(-Sum((a-b)**2)) with a=Var(0,3,0), b=Var(1,3,1), d=Var(3,1,0), f=Var(5,3,0) ... OK
[pyKeOps] Compiling pykeops cpp 7cfc01571c module ... OK
Loss after 1 iteration(s) : 2.93e-03
  = 2.93e-03 + 0 (fidelity + regularization_weight * regularization)

Extrapolation

back = model_norm.morph(
    shape=source,
    parameter=task_norm.parameter_,
    final_time=-1.0,
    return_path=True,
).path

model_norm.n_steps = 8
forward = model_norm.morph(
    shape=source,
    parameter=task_norm.parameter_,
    final_time=2.0,
    return_path=True,
).path

path = back[::-1] + forward[1:]

plotter = pv.Plotter()
plotter.open_gif("lddmm_normalization.gif", fps=4)
for i in range(len(path)):
    plotter.clear_actors()
    plotter.add_mesh(source.to_pyvista(), color="teal", opacity=0.2, **plot_kwargs)
    plotter.add_mesh(target.to_pyvista(), color="red", opacity=0.2, **plot_kwargs)
    plotter.add_mesh(path[i].to_pyvista(), color="tan", opacity=0.8, **plot_kwargs)
    plotter.camera_position = cpos
    plotter.write_frame()
plotter.close()
plot lddmm 1 normalization

Example with a more complex shape

n_steps = 3

plot_kwargs = {
    "smooth_shading": True,
    "pbr": True,
    "metallic": 0.7,
    "roughness": 0.6,

}

cpos = [(3.6401575998373183, -1.183408993703478, 1.0915912440258628),
 (0.7463583722710609, 0.762569822371006, 0.48035204596817493),
 (-0.1745415166347431, 0.04933887578777028, 0.9834129012306287)]

# 5 - 8
source = sks.PolyData("../data/cactus/cactus3.ply")
target = sks.PolyData("../data/cactus/cactus11.ply")
target.points += torch.Tensor([0.5, 0.5, 0])

decimation = sks.Decimation(n_points = 500)
source = decimation.fit_transform(source)
target = decimation.transform(target)


model = sks.ExtrinsicDeformation(
    n_steps=n_steps,
    kernel="gaussian",
    scale=0.1,
    normalization="both",
)

loss = sks.L2Loss()

Interpolation

task = sks.Registration(
    model=model,
    loss=loss,
    optimizer=sks.LBFGS(),
    n_iter=1,
    verbose=True,
    regularization_weight=0.001
)

start = time()
task.fit(source=source, target=target)
print("Elapsed time: ", time() - start)

path = task.path_

plotter = pv.Plotter()
for frame in path:
    plotter.add_mesh(frame.to_pyvista(), color="tan", opacity=0.3, **plot_kwargs)
plotter.add_mesh(source.to_pyvista(), color="teal", opacity=0.5, **plot_kwargs)
plotter.add_mesh(target.to_pyvista(), color="red", opacity=0.5, **plot_kwargs)
plotter.camera_position = cpos
plotter.show()
plot lddmm 1 normalization
Initial loss : 1.58e+01
  = 1.58e+01 + 0.001 * 0.00e+00 (fidelity + regularization_weight * regularization)
Loss after 1 iteration(s) : 2.36e-01
  = 1.11e-01 + 0.001 * 1.25e+02 (fidelity + regularization_weight * regularization)
Elapsed time:  16.563254833221436

Extrapolation

back = model.morph(
    shape=source,
    parameter=task.parameter_,
    return_path=True,
    return_regularization=True,
    final_time=-1.0
).path

model.n_steps = 2 * n_steps

forward = model.morph(
    shape=source,
    parameter=task.parameter_,
    return_path=True,
    return_regularization=True,
    final_time=2.0
).path

path = back[::-1] + forward[1:]

plotter = pv.Plotter()
for frame in path:
    plotter.add_mesh(frame.to_pyvista(), color="tan", opacity=0.3, **plot_kwargs)
plotter.add_mesh(source.to_pyvista(), color="teal", opacity=0.5, **plot_kwargs)
plotter.add_mesh(target.to_pyvista(), color="red", opacity=0.5, **plot_kwargs)
plotter.camera_position = cpos
plotter.show()

print(plotter.camera_position)
plot lddmm 1 normalization
[(3.6401575998373183, -1.183408993703478, 1.0915912440258628),
 (0.7463583722710609, 0.762569822371006, 0.48035204596817493),
 (-0.17454151663474313, 0.049338875787770284, 0.9834129012306289)]

Total running time of the script: (3 minutes 20.326 seconds)

Gallery generated by Sphinx-Gallery