.. DO NOT EDIT.
.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY.
.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE:
.. "_auto_tutorials/plot_modules.py"
.. LINE NUMBERS ARE GIVEN BELOW.

.. only:: html

    .. note::
        :class: sphx-glr-download-link-note

        Click :ref:`here <sphx_glr_download__auto_tutorials_plot_modules.py>`
        to download the full example code

.. rst-class:: sphx-glr-example-title

.. _sphx_glr__auto_tutorials_plot_modules.py:


Building more Complex Deformation Modules
=========================================

In this tutorial, we present the construction of the main deformation modules and display examples of vector fields they can generate.

.. GENERATED FROM PYTHON SOURCE LINES 9-14

Initialization
--------------

Import relevant Python modules.


.. GENERATED FROM PYTHON SOURCE LINES 14-29

.. code-block:: default


    import sys
    sys.path.append("../")
    import math

    import torch
    import matplotlib.pyplot as plt

    import imodal

    imodal.Utilities.set_compute_backend('torch')

    torch.manual_seed(1337)






.. rst-class:: sphx-glr-script-out

 Out:

 .. code-block:: none


    <torch._C.Generator object at 0x7ff78a592d68>



.. GENERATED FROM PYTHON SOURCE LINES 30-32

We define a grid on which we compute the generated vector fields.


.. GENERATED FROM PYTHON SOURCE LINES 32-36

.. code-block:: default


    grid_points = imodal.Utilities.grid2vec(*torch.meshgrid([torch.linspace(-2., 2., 20), torch.linspace(-2., 2., 20)]))









.. GENERATED FROM PYTHON SOURCE LINES 37-41

Sum of Local Translations (unstructured)
----------------------------------------
We define the parameters, the scale of gaussian kernel **sigma**, **d** the dimension of the ambiant space and **p** the number of local translations (points in the geometrical descriptor).


.. GENERATED FROM PYTHON SOURCE LINES 41-47

.. code-block:: default


    sigma = 0.5
    d = 2
    p = 5









.. GENERATED FROM PYTHON SOURCE LINES 48-51

There are two ways to build a sum of local translations module, either with **Translations** (explicit formulation) or with **ImplicitModule0** (implicit formulation).
The implicit formulation is a regularised version of the explicit one and depends on a regularization parameter **nu**.


.. GENERATED FROM PYTHON SOURCE LINES 51-58

.. code-block:: default


    explicit_translation = imodal.DeformationModules.Translations(d, p, sigma)

    nu = 0.1
    implicit_translation = imodal.DeformationModules.ImplicitModule0(d, p, sigma, nu=nu)









.. GENERATED FROM PYTHON SOURCE LINES 59-62

We choose the geometrical descriptor i.e. the centers **gd** carrying the local translations.
Then, we choose the controls **controls** i.e. the translation vectors.


.. GENERATED FROM PYTHON SOURCE LINES 62-73

.. code-block:: default


    gd = 0.8*torch.randn(p, d)
    controls = torch.rand(p, d) - 0.5

    explicit_translation.manifold.fill_gd(gd)
    implicit_translation.manifold.fill_gd(gd)

    explicit_translation.fill_controls(controls)
    implicit_translation.fill_controls(controls)









.. GENERATED FROM PYTHON SOURCE LINES 74-76

We compute and display the generated vector fields


.. GENERATED FROM PYTHON SOURCE LINES 76-100

.. code-block:: default


    explicit_field = explicit_translation(grid_points)
    implicit_field = implicit_translation(grid_points)

    plt.figure(figsize=[8., 4.])
    plt.subplot(1, 2, 1)
    plt.title("Explicit")
    plt.quiver(grid_points[:, 0], grid_points[:, 1], explicit_field[:, 0], explicit_field[:, 1])
    plt.plot(gd[:, 0], gd[:, 1], 'x', color='blue')
    plt.quiver(gd[:, 0], gd[:, 1], controls[:, 0], controls[:, 1], scale=5., color='red', lw=1.5)
    plt.axis('equal')
    plt.axis('off')

    plt.subplot(1, 2, 2)
    plt.title("Implicit")
    plt.quiver(grid_points[:, 0], grid_points[:, 1], implicit_field[:, 0], implicit_field[:, 1])
    plt.plot(gd[:, 0], gd[:, 1], 'x', color='blue')
    plt.quiver(gd[:, 0], gd[:, 1], controls[:, 0], controls[:, 1], scale=5., color='red', lw=1.5)
    plt.axis('equal')
    plt.axis('off')

    plt.show()





.. image:: /_auto_tutorials/images/sphx_glr_plot_modules_001.png
    :alt: Explicit, Implicit
    :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 101-107

Local Constrained Translations
------------------------------
We build two deformation modules, based on the class **LocalConstrainedTranslation**, generating respectively
one local scaling **local_scaling** and one local rotation **local_rotation**.
We define the parameters, the scale of gaussian kernel **sigma** and **d** the dimension of the ambiant space.


.. GENERATED FROM PYTHON SOURCE LINES 107-115

.. code-block:: default


    sigma = 1.
    d = 2

    local_scaling = imodal.DeformationModules.LocalScaling(d, sigma)
    local_rotation = imodal.DeformationModules.LocalRotation(d, sigma)









.. GENERATED FROM PYTHON SOURCE LINES 116-123

We choose the geometrical descriptor **gd** made of one point and the controls **controls** made of one scalar

.. note::
  The control dictate how strong the vector field will be, i.e.
  how much the ambiant space around the gaussian will respectively
  scale or rotate and the direction of the deformation.


.. GENERATED FROM PYTHON SOURCE LINES 123-134

.. code-block:: default


    gd = torch.zeros(1,d)
    controls = torch.ones(1)

    local_scaling.manifold.fill_gd(gd)
    local_rotation.manifold.fill_gd(gd)

    local_scaling.fill_controls(controls)
    local_rotation.fill_controls(controls)









.. GENERATED FROM PYTHON SOURCE LINES 135-138

We compute and display the generated vector fields (**scaling_field** and **rotation_field**) as well as 
the intermediate points and vectors used to build these fields (**support** and **vector**)


.. GENERATED FROM PYTHON SOURCE LINES 138-168

.. code-block:: default


    scaling_field = local_scaling(grid_points)
    rotation_field = local_rotation(grid_points)

    support_scaling = local_scaling._f_support(gd)
    vector_scaling = local_scaling._f_vectors(gd)
    support_rotation = local_rotation._f_support(gd)
    vector_rotation = local_rotation._f_vectors(gd)


    plt.figure(figsize=[8., 4.])
    plt.subplot(1, 2, 1)
    plt.title("Local scaling")
    plt.quiver(grid_points[:, 0], grid_points[:, 1], scaling_field[:, 0], scaling_field[:, 1], scale=8.)
    plt.plot(gd[:, 0], gd[:, 1], 'x', color='blue')
    plt.quiver(support_scaling[:, 0], support_scaling[:, 1], vector_scaling[:, 0], vector_scaling[:, 1], scale=10., color='red', lw=1.5)
    plt.axis('equal')
    plt.axis('off')

    plt.subplot(1, 2, 2)
    plt.title("Local rotation")
    plt.quiver(grid_points[:, 0], grid_points[:, 1], rotation_field[:, 0], rotation_field[:, 1], scale=8.)
    plt.plot(gd[:, 0], gd[:, 1], 'x', color='blue')
    plt.quiver(support_rotation[:, 0], support_rotation[:, 1], vector_rotation[:, 0], vector_rotation[:, 1], scale=10., color='red', lw=1.5)
    plt.axis('equal')
    plt.axis('off')

    plt.show()





.. image:: /_auto_tutorials/images/sphx_glr_plot_modules_002.png
    :alt: Local scaling, Local rotation
    :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 169-174

Implicit Deformation Module of Order 1
--------------------------------------
We will present here several examples of implicit deformation of order 1 and deformations they can generate.
In all these examples, the dimension of the control is :math:`p=1`.


.. GENERATED FROM PYTHON SOURCE LINES 177-179

We define the first parameters: the scale of gaussian kernel **sigma**, the dimension of the ambiant space **d** and the dimension of the control **p**.


.. GENERATED FROM PYTHON SOURCE LINES 179-186

.. code-block:: default


    sigma = 0.3
    d = 2
    p = 1
    nu = 0.001









.. GENERATED FROM PYTHON SOURCE LINES 187-189

We also need to specify the number of points **N** on which the constraints are imposed. We will initially define these constraints on a regular grid **grid_points** and then retrieve the number of points.


.. GENERATED FROM PYTHON SOURCE LINES 189-194

.. code-block:: default


    positions = torch.load("../data/unit_square_points.pt").to(dtype=torch.get_default_dtype())
    N = positions.shape[0]









.. GENERATED FROM PYTHON SOURCE LINES 195-198

The last parameter to set is the growth model tensor **C**. We recall that, if :math:`h` is the control, for each :math:`i` :math:`C_ih` defines the eigenvalues of the infinitesimal strain tensor of the generated vector field at the :math:`i`-th point of the geometrical descriptor.
We will present 3 different choices for this parameter, corresponding to 3 different constraints.


.. GENERATED FROM PYTHON SOURCE LINES 201-206

Uniform directional scaling
^^^^^^^^^^^^^^^^^^^^^^^^^^^

In a first example, we define the growth model tensor **C_directionalscaling** such that it imposes a uniform direction scaling along the first direction of the eigenvector, and no metric change along the second one.


.. GENERATED FROM PYTHON SOURCE LINES 206-211

.. code-block:: default


    C_directionalscaling = torch.zeros([N, d, p])
    C_directionalscaling[:, 0, :] = 1.









.. GENERATED FROM PYTHON SOURCE LINES 212-214

We define the corresponding implicit deformation module of order 1 **implicit**.


.. GENERATED FROM PYTHON SOURCE LINES 214-218

.. code-block:: default


    implicit = imodal.DeformationModules.ImplicitModule1(d, N, sigma, C_directionalscaling, 0.01)









.. GENERATED FROM PYTHON SOURCE LINES 219-225

We will present two generated vector field with two initialization of geometrical descriptors.

We choose first the geometrical descriptor **gd** made of **N** points **positions** and **N** rotation matrices **rot** equal to identity.
We recall that these rotation matrices define the eigenvectors of the infinitesimal strain tensor of the generated vector field at each point of the geometrical descriptor.
Then, we choose the controls **controls** made of one scalar.


.. GENERATED FROM PYTHON SOURCE LINES 225-235

.. code-block:: default


    rot = torch.stack([imodal.Utilities.rot2d(0.)]*positions.shape[0], axis=0)
    gd = (positions, rot)

    implicit.manifold.fill_gd(gd)

    controls = torch.ones(p) 
    implicit.fill_controls(controls)









.. GENERATED FROM PYTHON SOURCE LINES 236-245

We compute and display the growth factor corresponding to the infinitesimal strain tensor imposed at each point (defined by the eigenvalues and eigenvectors built previously).

There are two ways to display this growth factor:

  i. with oriented arrows along each eigenvector with a length proportional to absolute value of the associated eigenvalue, pointing outward (resp. inward) if it is positive (resp. negative)
  ii. with ellipses whose axis are given by the eigenvectors and the absolute value of the associated eigenvalues.

We then display the generated vector fields (**scaling_field** and **rotation_field**), and the infinitesimal deformation generated by it.


.. GENERATED FROM PYTHON SOURCE LINES 245-286

.. code-block:: default



    implicit_field = implicit(grid_points)
    step = 0.3
    new_grid_points = grid_points + step * implicit_field
    new_positions = positions + step * implicit(positions)

    plt.figure(figsize=[8., 8.])
    ax = plt.subplot(2, 2, 1)
    plt.title("Growth factor displayed with arrows")
    plt.plot(grid_points[:, 0], grid_points[:, 1], '.k', markersize=1)
    plt.plot(positions[:, 0], positions[:, 1], '.', color='blue')
    imodal.Utilities.plot_C_arrows(ax, positions, C_directionalscaling, R=rot, color='blue', scale=0.4, mutation_scale=8.)
    plt.axis('equal')
    plt.axis('off')

    ax = plt.subplot(2, 2, 2)
    plt.title("Growth factor displayed with ellipses")
    plt.plot(grid_points[:, 0], grid_points[:, 1], '.k', markersize=1)
    plt.plot(positions[:, 0], positions[:, 1], '.', color='blue')
    imodal.Utilities.plot_C_ellipses(ax, positions, C_directionalscaling, R=rot, color='blue', scale=0.3)
    plt.axis('equal')
    plt.axis('off')

    plt.subplot(2, 2, 3)
    plt.title("Generated vector field")
    plt.plot(positions[:, 0], positions[:, 1], '.', color='blue')
    plt.quiver(grid_points[:, 0], grid_points[:, 1], implicit_field[:, 0], implicit_field[:, 1], scale=10., width=.01)
    plt.axis('equal')
    plt.axis('off')

    ax = plt.subplot(2, 2, 4)
    plt.title("Infinitesimal deformation")
    plt.plot(new_grid_points[:, 0], new_grid_points[:, 1], '.k', markersize=1)
    plt.plot(new_positions[:, 0], new_positions[:, 1], '.', color='blue')
    plt.axis('equal')
    plt.axis('off')

    plt.show()





.. image:: /_auto_tutorials/images/sphx_glr_plot_modules_003.png
    :alt: Growth factor displayed with arrows, Growth factor displayed with ellipses, Generated vector field, Infinitesimal deformation
    :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 287-289

We now choose the **N** rotation matrices **rot** to be equal to the rotation matrix of angle :math:`\pi/2`.


.. GENERATED FROM PYTHON SOURCE LINES 289-338

.. code-block:: default



    rot = torch.stack([imodal.Utilities.rot2d(0.5 * math.pi)]*positions.shape[0], axis=0)
    gd=(positions, rot)

    implicit.manifold.fill_gd(gd)

    controls = torch.ones(p) 
    implicit.fill_controls(controls)

    implicit_field = implicit(grid_points)
    step = 0.3
    new_grid_points = grid_points + step * implicit_field
    new_positions = positions + step * implicit(positions)


    plt.figure(figsize=[8., 8.])
    ax = plt.subplot(2, 2, 1)
    plt.title("Growth factor displayed with arrows")
    plt.plot(grid_points[:, 0], grid_points[:, 1], '.k', markersize=1)
    plt.plot(positions[:, 0], positions[:, 1], '.', color='blue')
    imodal.Utilities.plot_C_arrows(ax, positions, C_directionalscaling, R=rot, color='blue', scale=0.4, mutation_scale=8.)
    plt.axis('equal')
    plt.axis('off')

    ax = plt.subplot(2, 2, 2)
    plt.title("Growth factor displayed with ellipses")
    plt.plot(grid_points[:, 0], grid_points[:, 1], '.k', markersize=1)
    plt.plot(positions[:, 0], positions[:, 1], '.', color='blue')
    imodal.Utilities.plot_C_ellipses(ax, positions, C_directionalscaling, R=rot, color='blue', scale=0.3)
    plt.axis('equal')
    plt.axis('off')

    plt.subplot(2, 2, 3)
    plt.title("Generated vector field")
    plt.plot(positions[:, 0], positions[:, 1], '.', color='blue')
    plt.quiver(grid_points[:, 0], grid_points[:, 1], implicit_field[:, 0], implicit_field[:, 1], scale=10., width=.01)
    plt.axis('equal')
    plt.axis('off')

    ax = plt.subplot(2, 2, 4)
    plt.title("Infinitesimal deformation")
    plt.plot(new_grid_points[:, 0], new_grid_points[:, 1], '.k', markersize=1)
    plt.plot(new_positions[:, 0], new_positions[:, 1], '.', color='blue')
    plt.axis('equal')
    plt.axis('off')
    plt.show()





.. image:: /_auto_tutorials/images/sphx_glr_plot_modules_004.png
    :alt: Growth factor displayed with arrows, Growth factor displayed with ellipses, Generated vector field, Infinitesimal deformation
    :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 339-341

The same result can be obtained with the growth model tensor **C_directionalscaling** imposing a uniform direction scaling along the second direction of the eigenvector, and no metric change along the first one and the N rotation matrices **rot** equal to the identity matrix.


.. GENERATED FROM PYTHON SOURCE LINES 341-393

.. code-block:: default


    C_directionalscaling = torch.zeros([N, d, p])
    C_directionalscaling[:, 1, :] = 1.

    implicit = imodal.DeformationModules.ImplicitModule1(d, N, sigma, C_directionalscaling, 0.01)

    rot = torch.stack([imodal.Utilities.rot2d(0.)]*positions.shape[0], axis=0)
    gd=(positions, rot)

    implicit.manifold.fill_gd(gd)

    implicit.fill_controls(controls)

    implicit_field = implicit(grid_points)
    step = 0.3
    new_grid_points = grid_points + step * implicit_field
    new_positions = positions + step * implicit(positions)


    plt.figure(figsize=[8., 8.])
    ax = plt.subplot(2, 2, 1)
    plt.title("Growth factor displayed with arrows")
    plt.plot(grid_points[:, 0], grid_points[:, 1], '.k', markersize=1)
    plt.plot(positions[:, 0], positions[:, 1], '.', color='blue')
    imodal.Utilities.plot_C_arrows(ax, positions, C_directionalscaling, R=rot, color='blue', scale=0.4, mutation_scale=8.)
    plt.axis('equal')
    plt.axis('off')

    ax = plt.subplot(2, 2, 2)
    plt.title("Growth factor displayed with ellipses")
    plt.plot(grid_points[:, 0], grid_points[:, 1], '.k', markersize=1)
    plt.plot(positions[:, 0], positions[:, 1], '.', color='blue')
    imodal.Utilities.plot_C_ellipses(ax, positions, C_directionalscaling, R=rot, color='blue', scale=0.3)
    plt.axis('equal')
    plt.axis('off')

    plt.subplot(2, 2, 3)
    plt.title("Generated vector field")
    plt.plot(positions[:, 0], positions[:, 1], '.', color='blue')
    plt.quiver(grid_points[:, 0], grid_points[:, 1], implicit_field[:, 0], implicit_field[:, 1], scale=10., width=.01)
    plt.axis('equal')
    plt.axis('off')

    ax = plt.subplot(2, 2, 4)
    plt.title("Infinitesimal deformation")
    plt.plot(new_grid_points[:, 0], new_grid_points[:, 1], '.k', markersize=1)
    plt.plot(new_positions[:, 0], new_positions[:, 1], '.', color='blue')
    plt.axis('equal')
    plt.axis('off')
    plt.show()





.. image:: /_auto_tutorials/images/sphx_glr_plot_modules_005.png
    :alt: Growth factor displayed with arrows, Growth factor displayed with ellipses, Generated vector field, Infinitesimal deformation
    :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 394-398

Uniform anisotropic scaling
^^^^^^^^^^^^^^^^^^^^^^^^^^^
We define now another implicit deformation module of order 1 generating a uniform scaling twice as important on the first eigenvector than on the second. The growth model tensor **C_anisotropicscaling** is defined as follows.


.. GENERATED FROM PYTHON SOURCE LINES 398-406

.. code-block:: default


    C_anisotropicscaling = torch.zeros([N, d, p])
    C_anisotropicscaling[:, 0, :] = 2.
    C_anisotropicscaling[:, 1, :] = 1.

    implicit = imodal.DeformationModules.ImplicitModule1(d, N, sigma, C_anisotropicscaling, 0.01)









.. GENERATED FROM PYTHON SOURCE LINES 407-409

We choose rotation matrices **rot** to be equal to the rotation matrix of angle :math:`\pi/4`.


.. GENERATED FROM PYTHON SOURCE LINES 409-455

.. code-block:: default

    rot = torch.stack([imodal.Utilities.rot2d(math.pi/4.)]*positions.shape[0], axis=0)
    gd=(positions, rot)

    implicit.manifold.fill_gd(gd)

    implicit.fill_controls(controls)

    implicit_field = implicit(grid_points)
    step = 0.3
    new_grid_points = grid_points + step * implicit_field
    new_positions = positions + step * implicit(positions)


    plt.figure(figsize=[8., 8.])
    ax = plt.subplot(2, 2, 1)
    plt.title("Growth factor displayed with arrows")
    plt.plot(grid_points[:, 0], grid_points[:, 1], '.k', markersize=1)
    plt.plot(positions[:, 0], positions[:, 1], '.', color='blue')
    imodal.Utilities.plot_C_arrows(ax, positions, C_anisotropicscaling, R=rot, color='blue', scale=0.3, mutation_scale=8.)
    plt.axis('equal')
    plt.axis('off')

    ax = plt.subplot(2, 2, 2)
    plt.title("Growth factor displayed with ellipses")
    plt.plot(grid_points[:, 0], grid_points[:, 1], '.k', markersize=1)
    plt.plot(positions[:, 0], positions[:, 1], '.', color='blue')
    imodal.Utilities.plot_C_ellipses(ax, positions, C_anisotropicscaling, R=rot, color='blue', scale=0.15)
    plt.axis('equal')
    plt.axis('off')

    plt.subplot(2, 2, 3)
    plt.title("Generated vector field")
    plt.plot(positions[:, 0], positions[:, 1], '.', color='blue')
    plt.quiver(grid_points[:, 0], grid_points[:, 1], implicit_field[:, 0], implicit_field[:, 1], scale=20., width=.01)
    plt.axis('equal')
    plt.axis('off')

    ax = plt.subplot(2, 2, 4)
    plt.title("Infinitesimal deformation")
    plt.plot(new_grid_points[:, 0], new_grid_points[:, 1], '.k', markersize=1)
    plt.plot(new_positions[:, 0], new_positions[:, 1], '.', color='blue')
    plt.axis('equal')
    plt.axis('off')
    plt.show()





.. image:: /_auto_tutorials/images/sphx_glr_plot_modules_006.png
    :alt: Growth factor displayed with arrows, Growth factor displayed with ellipses, Generated vector field, Infinitesimal deformation
    :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 456-462

Non uniform directional scaling
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
We present a last another implicit deformation module of order 1 with a non uniform growth model tensor **C_non_unif**. 
It imposes a non uniform scaling on the second eigenvector, with a scaling factor depending on the x-coordinates of the points.
It is defined as follows.


.. GENERATED FROM PYTHON SOURCE LINES 462-467

.. code-block:: default


    C_non_unif = torch.zeros([N, d, p])
    C_non_unif[:, 1, 0] = positions[:,0] + 1.









.. GENERATED FROM PYTHON SOURCE LINES 468-470

We define the corresponding implicit deformation module of order 1 **implicit**.


.. GENERATED FROM PYTHON SOURCE LINES 470-474

.. code-block:: default


    implicit = imodal.DeformationModules.ImplicitModule1(d, N, sigma, C_non_unif, 0.01)









.. GENERATED FROM PYTHON SOURCE LINES 475-477

We choose rotation matrices **rot** to be equal to the identity matrix.


.. GENERATED FROM PYTHON SOURCE LINES 477-524

.. code-block:: default


    rot = torch.stack([imodal.Utilities.rot2d(0.)]*positions.shape[0], axis=0)
    gd=(positions, rot)

    implicit.manifold.fill_gd(gd)

    implicit.fill_controls(controls)

    implicit_field = implicit(grid_points)
    step = 0.3
    new_grid_points = grid_points + step * implicit_field
    new_positions = positions + step * implicit(positions)


    plt.figure(figsize=[8., 8.])
    ax = plt.subplot(2, 2, 1)
    plt.title("Growth factor displayed with arrows")
    plt.plot(grid_points[:, 0], grid_points[:, 1], '.k', markersize=1)
    plt.plot(positions[:, 0], positions[:, 1], '.', color='blue')
    imodal.Utilities.plot_C_arrows(ax, positions, C_non_unif, R=rot, color='blue', scale=0.4, mutation_scale=8.)
    plt.axis('equal')
    plt.axis('off')

    ax = plt.subplot(2, 2, 2)
    plt.title("Growth factor displayed with ellipses")
    plt.plot(grid_points[:, 0], grid_points[:, 1], '.k', markersize=1)
    plt.plot(positions[:, 0], positions[:, 1], '.', color='blue')
    imodal.Utilities.plot_C_ellipses(ax, positions, C_non_unif, R=rot, color='blue', scale=0.2)
    plt.axis('equal')
    plt.axis('off')

    plt.subplot(2, 2, 3)
    plt.title("Generated vector field")
    plt.plot(positions[:, 0], positions[:, 1], '.', color='blue')
    plt.quiver(grid_points[:, 0], grid_points[:, 1], implicit_field[:, 0], implicit_field[:, 1], scale=20., width=.01)
    plt.axis('equal')
    plt.axis('off')

    ax = plt.subplot(2, 2, 4)
    plt.title("Infinitesimal deformation")
    plt.plot(new_grid_points[:, 0], new_grid_points[:, 1], '.k', markersize=1)
    plt.plot(new_positions[:, 0], new_positions[:, 1], '.', color='blue')
    plt.axis('equal')
    plt.axis('off')
    plt.show()





.. image:: /_auto_tutorials/images/sphx_glr_plot_modules_007.png
    :alt: Growth factor displayed with arrows, Growth factor displayed with ellipses, Generated vector field, Infinitesimal deformation
    :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 525-530

Compound Deformation Module
---------------------------
We present an example of the combination **compound** of two deformation modules: the previous implicit deformation module of order one **implicit** (which we rebuild) and one generating one local translation **translation**.
We will show an example of modular large deformation generated by this compound deformation module.


.. GENERATED FROM PYTHON SOURCE LINES 530-555

.. code-block:: default


    d = 2

    sigma_implicit = 0.5
    N_implicit = N
    p_implicit = 1
    nu_implicit = 0.001

    rot = torch.stack([imodal.Utilities.rot2d(0.)]*positions.shape[0], axis=0)
    C_non_unif = torch.zeros([N, d, p])
    C_non_unif[:, 1, 0] = positions[:,0] + 1.
    implicit = imodal.DeformationModules.ImplicitModule1(d, N_implicit, sigma_implicit, C_non_unif, 0.01, gd=(positions, rot))
    implicit.fill_controls(torch.ones(p_implicit))


    sigma_translation = 0.5
    N_translation = 1
    gd_translation = torch.tensor([[0., 1.]])
    translation = imodal.DeformationModules.Translations(d, N_translation, sigma_translation, gd=gd_translation)
    control_translation = torch.tensor([[0., 2.]])
    translation.fill_controls(control_translation)

    compound = imodal.DeformationModules.CompoundModule([implicit, translation])









.. GENERATED FROM PYTHON SOURCE LINES 556-559

We display the growth factor and the translation vector.
We then display the generated vector fields (**scaling_field** and **rotation_field**), and the infinitesimal deformation generated by it.


.. GENERATED FROM PYTHON SOURCE LINES 559-599

.. code-block:: default



    compound_field = compound(grid_points)
    step = 0.2
    new_grid_points = grid_points + step * compound_field
    new_positions = positions + step * compound(positions)
    new_gd_translation = gd_translation + step * compound(gd_translation)


    fig = plt.figure(figsize=[12., 4.])
    ax = plt.subplot(1, 3, 1)
    plt.title("Growth factor")
    plt.plot(grid_points[:, 0], grid_points[:, 1], '.k', markersize=1)
    plt.plot(positions[:, 0], positions[:, 1], '.', color='blue')
    imodal.Utilities.plot_C_ellipses(ax, positions, C_non_unif, R=rot, color='blue', scale=0.2)
    plt.plot(gd_translation[:,0], gd_translation[:,1], 'xb')
    plt.quiver(gd_translation[:,0], gd_translation[:,1], control_translation[:,0], control_translation[:,1], color='green', scale=30.)
    plt.axis('equal')
    plt.axis('off')

    plt.subplot(1, 3, 2)
    plt.title("Generated vector field")
    plt.plot(positions[:, 0], positions[:, 1], '.', color='blue')
    plt.quiver(grid_points[:, 0], grid_points[:, 1], implicit_field[:, 0], implicit_field[:, 1], scale=20., width=.01)
    plt.plot(gd_translation[:,0], gd_translation[:,1], 'xb')
    plt.axis('equal')
    plt.axis('off')

    ax = plt.subplot(1, 3, 3)
    plt.title("Infinitesimal deformation")
    plt.plot(new_grid_points[:, 0], new_grid_points[:, 1], '.k', markersize=1)
    plt.plot(new_positions[:, 0], new_positions[:, 1], '.', color='blue')
    plt.plot(new_gd_translation[:,0], new_gd_translation[:,1], 'xb')
    plt.axis('equal')
    plt.axis('off')

    fig.tight_layout()
    plt.show()





.. image:: /_auto_tutorials/images/sphx_glr_plot_modules_008.png
    :alt: Growth factor, Generated vector field, Infinitesimal deformation
    :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 600-603

In order to better understand this compound module, we present a modular large deformation generated by it.
It is parametrized by an initial momentum which we set to zero except for **cotan_translation** associated to the local translation and **cotan_implicit_points** associated to the points of the geometrical descriptor of the implicit deformation module.


.. GENERATED FROM PYTHON SOURCE LINES 603-612

.. code-block:: default


    cotan_translation = torch.tensor([[0., 1.]])
    translation.manifold.fill_cotan(cotan_translation)

    cotan_implicit_points = torch.zeros_like(positions)
    cotan_implicit_points[0,1] = -5.
    implicit.manifold.fill_cotan((cotan_implicit_points, torch.zeros_like(rot)))









.. GENERATED FROM PYTHON SOURCE LINES 613-615

In order to keep track of the grid deformation, we define a silent deformation module **silent** whose points are the grid points. It is built from the class **SilentLandmarks**.


.. GENERATED FROM PYTHON SOURCE LINES 615-619

.. code-block:: default


    silent = imodal.DeformationModules.SilentLandmarks(dim=2, nb_pts=grid_points.shape[0], gd=grid_points.clone())









.. GENERATED FROM PYTHON SOURCE LINES 620-622

We solve the shooting equations. 


.. GENERATED FROM PYTHON SOURCE LINES 622-629

.. code-block:: default


    shoot_method = 'euler'
    shoot_it = 10
    intermediates = {}
    imodal.HamiltonianDynamic.shoot(imodal.HamiltonianDynamic.Hamiltonian([silent, implicit, translation]), shoot_method, shoot_it, intermediates=intermediates)









.. GENERATED FROM PYTHON SOURCE LINES 630-633

We display the deformed points, the vector of the translation and the growth factor at each time. 
Note that the growth model tensor **C_non_unif** is a fixed parameter that does not evolve during the integration of the flow but that the growth factor (constraining the infinitesimal strain tensor and illustrated by the blue ellipses) built from **C_non_unif**,  the control **control_translation_t** and the rotation matrices **rot_t** do evolve.


.. GENERATED FROM PYTHON SOURCE LINES 633-658

.. code-block:: default


    display_index = [0, 3, 5, 7, 9]
    aabb = imodal.Utilities.AABB.build_from_points(grid_points).scale(1.5)

    fig = plt.figure(figsize=[20., 4.])
    for count, i in enumerate(display_index):
        ax = plt.subplot(1, 5, count+1)
        grid_points_t = intermediates['states'][i][0].gd.detach()
        positions_t = intermediates['states'][i][1].gd[0].detach()
        control_implicit_t = intermediates['controls'][i][1].detach()
        rot_t = intermediates['states'][i][1].gd[1].detach()
        gd_translation_t = intermediates['states'][i][2].gd.detach()
        control_translation_t = intermediates['controls'][i][2].detach()
        plt.plot(grid_points_t[:, 0], grid_points_t[:, 1], '.k', markersize=1)
        plt.plot(positions_t[:, 0], positions_t[:, 1], '.', color='blue', markersize=3)
        imodal.Utilities.plot_C_ellipses(ax, positions_t, control_implicit_t*C_non_unif, R=rot_t, color='blue', scale=1.)
        plt.plot(gd_translation_t[:,0], gd_translation_t[:,1], 'xb')
        plt.quiver(gd_translation_t[:,0], gd_translation_t[:,1], control_translation_t[:,0], control_translation_t[:,1], color='green', scale=5., width=.02)
        # plt.axis('equal')
        plt.axis(aabb.totuple())
        plt.axis('off')

    fig.tight_layout()
    plt.show()




.. image:: /_auto_tutorials/images/sphx_glr_plot_modules_009.png
    :alt: plot modules
    :class: sphx-glr-single-img






.. rst-class:: sphx-glr-timing

   **Total running time of the script:** ( 0 minutes  11.648 seconds)


.. _sphx_glr_download__auto_tutorials_plot_modules.py:


.. only :: html

 .. container:: sphx-glr-footer
    :class: sphx-glr-footer-example



  .. container:: sphx-glr-download sphx-glr-download-python

     :download:`Download Python source code: plot_modules.py <plot_modules.py>`



  .. container:: sphx-glr-download sphx-glr-download-jupyter

     :download:`Download Jupyter notebook: plot_modules.ipynb <plot_modules.ipynb>`


.. only:: html

 .. rst-class:: sphx-glr-signature

    `Gallery generated by Sphinx-Gallery <https://sphinx-gallery.github.io>`_