Switch to side-by-side view

--- a
+++ b/docs/mesh/meshRegistration.html
@@ -0,0 +1,394 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
+<meta name="generator" content="pdoc 0.10.0" />
+<title>pymskt.mesh.meshRegistration API documentation</title>
+<meta name="description" content="" />
+<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
+<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
+<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
+<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
+<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
+<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
+<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
+<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
+</head>
+<body>
+<main>
+<article id="content">
+<header>
+<h1 class="title">Module <code>pymskt.mesh.meshRegistration</code></h1>
+</header>
+<section id="section-intro">
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">import sys
+import vtk 
+try:
+     import pyfocusr
+except ModuleNotFoundError:
+    print(&#39;pyfocusr not found&#39;)
+    print(&#39;If you are not using the registration tools, you can ignore this message.&#39;)
+    print(&#39;install pyfocusr as described in the README: https://github.com/gattia/pymskt&#39;)
+    print(&#39;or visit the pyfocusr github repo: https://github.com/gattia/pyfocusr&#39;)
+
+import numpy as np
+
+def get_icp_transform(source, target, max_n_iter=1000, n_landmarks=1000, reg_mode=&#39;similarity&#39;):
+    &#34;&#34;&#34;
+    Get the Interative Closest Point (ICP) transformation from the `source` mesh to the
+    `target` mesh. 
+
+    Parameters
+    ----------
+    source : vtk.vtkPolyData
+        Source mesh that we want to transform onto the target mesh. 
+    target : vtk.vtkPolyData
+        Target mesh that we want to transform the source mesh onto. 
+    max_n_iter : int, optional
+        Max number of iterations for the registration algorithm to perform, by default 1000
+    n_landmarks : int, optional
+        How many landmarks to sample when determining distance between meshes &amp; 
+        solving for the optimal transformation, by default 1000
+    reg_mode : str, optional
+        The type of registration to perform. The options are: 
+            - &#39;rigid&#39;: true rigid, translation only 
+            - &#39;similarity&#39;: rigid + equal scale 
+        by default &#39;similarity&#39;
+
+    Returns
+    -------
+    vtk.vtkIterativeClosestPointTransform
+        The actual transform object after running the registration. 
+    &#34;&#34;&#34;    
+
+    icp = vtk.vtkIterativeClosestPointTransform()
+    icp.SetSource(source)
+    icp.SetTarget(target)
+    if reg_mode == &#39;rigid&#39;:
+        icp.GetLandmarkTransform().SetModeToRigidBody()
+    elif reg_mode == &#39;similarity&#39;:
+        icp.GetLandmarkTransform().SetModeToSimilarity()
+    icp.SetMaximumNumberOfIterations(max_n_iter)
+    icp.StartByMatchingCentroidsOn()
+    icp.Modified()
+    icp.Update()
+    icp.SetMaximumNumberOfLandmarks(n_landmarks)
+    return icp
+
+def non_rigidly_register(
+    target_mesh=None,
+    source_mesh=None,
+    final_pt_location=&#39;weighted_average&#39;,   # &#39;weighted_average&#39; or &#39;nearest_neighbour&#39;
+    icp_register_first=True,                # Get bones/objects into roughly the same alignment first
+    icp_registration_mode=&#39;similarity&#39;,     # similarity = rigid + scaling (isotropic), (&#34;rigid&#34;, &#34;similarity&#34;, &#34;affine&#34;)
+    icp_reg_target_to_source=True,          # For shape models, the source is usually the reference so we want target in its space (true)
+    n_spectral_features=3,
+    n_extra_spectral=3,                     # For ensuring we have the right spec coords - determined using wasserstein distances. 
+    target_eigenmap_as_reference=True,
+    get_weighted_spectral_coords=False,
+    list_features_to_calc=[&#39;curvature&#39;],    # &#39;curvature&#39;, min_curvature&#39; &#39;max_curvature&#39; (other features for registration)
+    use_features_as_coords=True,            # During registraiton - do we want to use curvature etc. 
+    rigid_reg_max_iterations=100,
+    non_rigid_alpha=0.01,
+    non_rigid_beta=50,
+    non_rigid_n_eigens=100,                 # number of eigens for low rank CPD registration
+    non_rigid_max_iterations=500,
+    rigid_before_non_rigid_reg=False,       # This is of the spectral coordinates - not the x/y/z used in icp_register_first
+    projection_smooth_iterations=30,        # Used for distributing registered points onto target surface - helps preserve diffeomorphism
+    graph_smoothing_iterations=300,         # For smoothing the target mesh before final point correspondence
+    feature_smoothing_iterations=30,        # how much should features (curvature) be smoothed before registration 
+    include_points_as_features=False,       # Do we want to incldue x/y/z positions in registration? 
+    norm_physical_and_spectral=True,        # set standardized mean and variance for each feature
+    feature_weights=np.diag([.1,.1]),       # should we weight the extra features (curvature) more/less than spectral
+    n_coords_spectral_ordering=20000,       # How many points on mesh to use for ordering spectral coordinates ()
+    n_coords_spectral_registration=1000,    # How many points to use for spectral registrtaion (usually random subsample)
+    initial_correspondence_type=&#39;kd&#39;,       # kd = nearest neightbor, hungarian = minimum cost of assigning between graphs (more compute heavy)
+    final_correspondence_type=&#39;kd&#39;          # kd = nearest neightbor, hungarian = minimum cost of assigning between graphs (more compute heavy)
+):
+    
+    if &#39;pyfocusr&#39; not in sys.modules:
+        raise ModuleNotFoundError(&#39;pyfocusr is not installed &amp; is necessary for non-rigid registration.&#39;)
+
+    if final_pt_location not in [&#39;weighted_average&#39;, &#39;nearest_neighbour&#39;]:
+        raise Exception(&#39;Did not specify appropriate final_pt_location, must be either &#34;weighted_average&#34;, or &#34;nearest_neighbour&#34;&#39;)
+
+    # Test if mesh is a vtk mesh, or a pymsky.Mesh object. 
+    if isinstance(target_mesh, vtk.vtkPolyData):
+        vtk_mesh_target = target_mesh
+    else:
+        try:
+            vtk_mesh_target = target_mesh.mesh
+        except:
+            raise Exception(f&#39;expected type vtk.vtkPolyData or pymskt.mesh.Mesh, got: {type(target_mesh)}&#39;)
+    
+    if isinstance(source_mesh, vtk.vtkPolyData):
+        vtk_mesh_source = source_mesh
+    else:
+        try:
+            vtk_mesh_source = source_mesh.mesh
+        except:
+            raise Exception(f&#39;expected type vtk.vtkPolyData or pymskt.mesh.Mesh, got: {type(target_mesh)}&#39;)
+    
+    reg = pyfocusr.Focusr(
+        vtk_mesh_target=vtk_mesh_target, 
+        vtk_mesh_source=vtk_mesh_source,  
+        icp_register_first=icp_register_first,
+        icp_registration_mode=icp_registration_mode,
+        icp_reg_target_to_source=icp_reg_target_to_source,
+        n_spectral_features=n_spectral_features,
+        n_extra_spectral=n_extra_spectral,
+        target_eigenmap_as_reference=target_eigenmap_as_reference,
+        get_weighted_spectral_coords=get_weighted_spectral_coords,
+        list_features_to_calc=list_features_to_calc,
+        use_features_as_coords=use_features_as_coords,
+        rigid_reg_max_iterations=rigid_reg_max_iterations,
+        non_rigid_alpha=non_rigid_alpha,
+        non_rigid_beta=non_rigid_beta,
+        non_rigid_n_eigens=non_rigid_n_eigens,
+        non_rigid_max_iterations=non_rigid_max_iterations,
+        rigid_before_non_rigid_reg=rigid_before_non_rigid_reg,
+        projection_smooth_iterations=projection_smooth_iterations,
+        graph_smoothing_iterations=graph_smoothing_iterations,
+        feature_smoothing_iterations=feature_smoothing_iterations,
+        include_points_as_features=include_points_as_features,
+        norm_physical_and_spectral=norm_physical_and_spectral,
+        feature_weights=feature_weights,
+        n_coords_spectral_ordering=n_coords_spectral_ordering,
+        n_coords_spectral_registration=n_coords_spectral_registration,
+        initial_correspondence_type=initial_correspondence_type,
+        final_correspondence_type=final_correspondence_type
+    ) 
+    reg.align_maps()
+
+    if final_pt_location == &#39;weighted_average&#39;:
+        reg.get_source_mesh_transformed_weighted_avg()
+        mesh_transformed_to_target = reg.weighted_avg_transformed_mesh
+    elif final_pt_location == &#39;nearest_neighbour&#39;:
+        reg.get_source_mesh_transformed_nearest_neighbour()
+        mesh_transformed_to_target = reg.nearest_neighbour_transformed_mesh
+        
+    return mesh_transformed_to_target    </code></pre>
+</details>
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+<h2 class="section-title" id="header-functions">Functions</h2>
+<dl>
+<dt id="pymskt.mesh.meshRegistration.get_icp_transform"><code class="name flex">
+<span>def <span class="ident">get_icp_transform</span></span>(<span>source, target, max_n_iter=1000, n_landmarks=1000, reg_mode='similarity')</span>
+</code></dt>
+<dd>
+<div class="desc"><p>Get the Interative Closest Point (ICP) transformation from the <code>source</code> mesh to the
+<code>target</code> mesh. </p>
+<h2 id="parameters">Parameters</h2>
+<dl>
+<dt><strong><code>source</code></strong> :&ensp;<code>vtk.vtkPolyData</code></dt>
+<dd>Source mesh that we want to transform onto the target mesh.</dd>
+<dt><strong><code>target</code></strong> :&ensp;<code>vtk.vtkPolyData</code></dt>
+<dd>Target mesh that we want to transform the source mesh onto.</dd>
+<dt><strong><code>max_n_iter</code></strong> :&ensp;<code>int</code>, optional</dt>
+<dd>Max number of iterations for the registration algorithm to perform, by default 1000</dd>
+<dt><strong><code>n_landmarks</code></strong> :&ensp;<code>int</code>, optional</dt>
+<dd>How many landmarks to sample when determining distance between meshes &amp;
+solving for the optimal transformation, by default 1000</dd>
+<dt><strong><code>reg_mode</code></strong> :&ensp;<code>str</code>, optional</dt>
+<dd>The type of registration to perform. The options are:
+- 'rigid': true rigid, translation only
+- 'similarity': rigid + equal scale
+by default 'similarity'</dd>
+</dl>
+<h2 id="returns">Returns</h2>
+<dl>
+<dt><code>vtk.vtkIterativeClosestPointTransform</code></dt>
+<dd>The actual transform object after running the registration.</dd>
+</dl></div>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def get_icp_transform(source, target, max_n_iter=1000, n_landmarks=1000, reg_mode=&#39;similarity&#39;):
+    &#34;&#34;&#34;
+    Get the Interative Closest Point (ICP) transformation from the `source` mesh to the
+    `target` mesh. 
+
+    Parameters
+    ----------
+    source : vtk.vtkPolyData
+        Source mesh that we want to transform onto the target mesh. 
+    target : vtk.vtkPolyData
+        Target mesh that we want to transform the source mesh onto. 
+    max_n_iter : int, optional
+        Max number of iterations for the registration algorithm to perform, by default 1000
+    n_landmarks : int, optional
+        How many landmarks to sample when determining distance between meshes &amp; 
+        solving for the optimal transformation, by default 1000
+    reg_mode : str, optional
+        The type of registration to perform. The options are: 
+            - &#39;rigid&#39;: true rigid, translation only 
+            - &#39;similarity&#39;: rigid + equal scale 
+        by default &#39;similarity&#39;
+
+    Returns
+    -------
+    vtk.vtkIterativeClosestPointTransform
+        The actual transform object after running the registration. 
+    &#34;&#34;&#34;    
+
+    icp = vtk.vtkIterativeClosestPointTransform()
+    icp.SetSource(source)
+    icp.SetTarget(target)
+    if reg_mode == &#39;rigid&#39;:
+        icp.GetLandmarkTransform().SetModeToRigidBody()
+    elif reg_mode == &#39;similarity&#39;:
+        icp.GetLandmarkTransform().SetModeToSimilarity()
+    icp.SetMaximumNumberOfIterations(max_n_iter)
+    icp.StartByMatchingCentroidsOn()
+    icp.Modified()
+    icp.Update()
+    icp.SetMaximumNumberOfLandmarks(n_landmarks)
+    return icp</code></pre>
+</details>
+</dd>
+<dt id="pymskt.mesh.meshRegistration.non_rigidly_register"><code class="name flex">
+<span>def <span class="ident">non_rigidly_register</span></span>(<span>target_mesh=None, source_mesh=None, final_pt_location='weighted_average', icp_register_first=True, icp_registration_mode='similarity', icp_reg_target_to_source=True, n_spectral_features=3, n_extra_spectral=3, target_eigenmap_as_reference=True, get_weighted_spectral_coords=False, list_features_to_calc=['curvature'], use_features_as_coords=True, rigid_reg_max_iterations=100, non_rigid_alpha=0.01, non_rigid_beta=50, non_rigid_n_eigens=100, non_rigid_max_iterations=500, rigid_before_non_rigid_reg=False, projection_smooth_iterations=30, graph_smoothing_iterations=300, feature_smoothing_iterations=30, include_points_as_features=False, norm_physical_and_spectral=True, feature_weights=array([[0.1, 0. ],
+[0. , 0.1]]), n_coords_spectral_ordering=20000, n_coords_spectral_registration=1000, initial_correspondence_type='kd', final_correspondence_type='kd')</span>
+</code></dt>
+<dd>
+<div class="desc"></div>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def non_rigidly_register(
+    target_mesh=None,
+    source_mesh=None,
+    final_pt_location=&#39;weighted_average&#39;,   # &#39;weighted_average&#39; or &#39;nearest_neighbour&#39;
+    icp_register_first=True,                # Get bones/objects into roughly the same alignment first
+    icp_registration_mode=&#39;similarity&#39;,     # similarity = rigid + scaling (isotropic), (&#34;rigid&#34;, &#34;similarity&#34;, &#34;affine&#34;)
+    icp_reg_target_to_source=True,          # For shape models, the source is usually the reference so we want target in its space (true)
+    n_spectral_features=3,
+    n_extra_spectral=3,                     # For ensuring we have the right spec coords - determined using wasserstein distances. 
+    target_eigenmap_as_reference=True,
+    get_weighted_spectral_coords=False,
+    list_features_to_calc=[&#39;curvature&#39;],    # &#39;curvature&#39;, min_curvature&#39; &#39;max_curvature&#39; (other features for registration)
+    use_features_as_coords=True,            # During registraiton - do we want to use curvature etc. 
+    rigid_reg_max_iterations=100,
+    non_rigid_alpha=0.01,
+    non_rigid_beta=50,
+    non_rigid_n_eigens=100,                 # number of eigens for low rank CPD registration
+    non_rigid_max_iterations=500,
+    rigid_before_non_rigid_reg=False,       # This is of the spectral coordinates - not the x/y/z used in icp_register_first
+    projection_smooth_iterations=30,        # Used for distributing registered points onto target surface - helps preserve diffeomorphism
+    graph_smoothing_iterations=300,         # For smoothing the target mesh before final point correspondence
+    feature_smoothing_iterations=30,        # how much should features (curvature) be smoothed before registration 
+    include_points_as_features=False,       # Do we want to incldue x/y/z positions in registration? 
+    norm_physical_and_spectral=True,        # set standardized mean and variance for each feature
+    feature_weights=np.diag([.1,.1]),       # should we weight the extra features (curvature) more/less than spectral
+    n_coords_spectral_ordering=20000,       # How many points on mesh to use for ordering spectral coordinates ()
+    n_coords_spectral_registration=1000,    # How many points to use for spectral registrtaion (usually random subsample)
+    initial_correspondence_type=&#39;kd&#39;,       # kd = nearest neightbor, hungarian = minimum cost of assigning between graphs (more compute heavy)
+    final_correspondence_type=&#39;kd&#39;          # kd = nearest neightbor, hungarian = minimum cost of assigning between graphs (more compute heavy)
+):
+    
+    if &#39;pyfocusr&#39; not in sys.modules:
+        raise ModuleNotFoundError(&#39;pyfocusr is not installed &amp; is necessary for non-rigid registration.&#39;)
+
+    if final_pt_location not in [&#39;weighted_average&#39;, &#39;nearest_neighbour&#39;]:
+        raise Exception(&#39;Did not specify appropriate final_pt_location, must be either &#34;weighted_average&#34;, or &#34;nearest_neighbour&#34;&#39;)
+
+    # Test if mesh is a vtk mesh, or a pymsky.Mesh object. 
+    if isinstance(target_mesh, vtk.vtkPolyData):
+        vtk_mesh_target = target_mesh
+    else:
+        try:
+            vtk_mesh_target = target_mesh.mesh
+        except:
+            raise Exception(f&#39;expected type vtk.vtkPolyData or pymskt.mesh.Mesh, got: {type(target_mesh)}&#39;)
+    
+    if isinstance(source_mesh, vtk.vtkPolyData):
+        vtk_mesh_source = source_mesh
+    else:
+        try:
+            vtk_mesh_source = source_mesh.mesh
+        except:
+            raise Exception(f&#39;expected type vtk.vtkPolyData or pymskt.mesh.Mesh, got: {type(target_mesh)}&#39;)
+    
+    reg = pyfocusr.Focusr(
+        vtk_mesh_target=vtk_mesh_target, 
+        vtk_mesh_source=vtk_mesh_source,  
+        icp_register_first=icp_register_first,
+        icp_registration_mode=icp_registration_mode,
+        icp_reg_target_to_source=icp_reg_target_to_source,
+        n_spectral_features=n_spectral_features,
+        n_extra_spectral=n_extra_spectral,
+        target_eigenmap_as_reference=target_eigenmap_as_reference,
+        get_weighted_spectral_coords=get_weighted_spectral_coords,
+        list_features_to_calc=list_features_to_calc,
+        use_features_as_coords=use_features_as_coords,
+        rigid_reg_max_iterations=rigid_reg_max_iterations,
+        non_rigid_alpha=non_rigid_alpha,
+        non_rigid_beta=non_rigid_beta,
+        non_rigid_n_eigens=non_rigid_n_eigens,
+        non_rigid_max_iterations=non_rigid_max_iterations,
+        rigid_before_non_rigid_reg=rigid_before_non_rigid_reg,
+        projection_smooth_iterations=projection_smooth_iterations,
+        graph_smoothing_iterations=graph_smoothing_iterations,
+        feature_smoothing_iterations=feature_smoothing_iterations,
+        include_points_as_features=include_points_as_features,
+        norm_physical_and_spectral=norm_physical_and_spectral,
+        feature_weights=feature_weights,
+        n_coords_spectral_ordering=n_coords_spectral_ordering,
+        n_coords_spectral_registration=n_coords_spectral_registration,
+        initial_correspondence_type=initial_correspondence_type,
+        final_correspondence_type=final_correspondence_type
+    ) 
+    reg.align_maps()
+
+    if final_pt_location == &#39;weighted_average&#39;:
+        reg.get_source_mesh_transformed_weighted_avg()
+        mesh_transformed_to_target = reg.weighted_avg_transformed_mesh
+    elif final_pt_location == &#39;nearest_neighbour&#39;:
+        reg.get_source_mesh_transformed_nearest_neighbour()
+        mesh_transformed_to_target = reg.nearest_neighbour_transformed_mesh
+        
+    return mesh_transformed_to_target    </code></pre>
+</details>
+</dd>
+</dl>
+</section>
+<section>
+</section>
+</article>
+<nav id="sidebar">
+<h1>Index</h1>
+<div class="toc">
+<ul></ul>
+</div>
+<ul id="index">
+<li><h3>Super-module</h3>
+<ul>
+<li><code><a title="pymskt.mesh" href="index.html">pymskt.mesh</a></code></li>
+</ul>
+</li>
+<li><h3><a href="#header-functions">Functions</a></h3>
+<ul class="">
+<li><code><a title="pymskt.mesh.meshRegistration.get_icp_transform" href="#pymskt.mesh.meshRegistration.get_icp_transform">get_icp_transform</a></code></li>
+<li><code><a title="pymskt.mesh.meshRegistration.non_rigidly_register" href="#pymskt.mesh.meshRegistration.non_rigidly_register">non_rigidly_register</a></code></li>
+</ul>
+</li>
+</ul>
+</nav>
+</main>
+<footer id="footer">
+<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
+</footer>
+</body>
+</html>
\ No newline at end of file