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

.. only:: html

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

        :ref:`Go to the end <sphx_glr_download_auto_examples_04_demos_viz_dt_ellipsoids.py>`
        to download the full example code

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

.. _sphx_glr_auto_examples_04_demos_viz_dt_ellipsoids.py:


===============================================================================
Display Tensor Ellipsoids for DTI using tensor_slicer vs ellipsoid actor
===============================================================================
This tutorial is intended to show two ways of displaying diffusion tensor
ellipsoids for DTI visualization. The first is using the usual
``tensor_slicer`` that allows us to slice many tensors as ellipsoids. The
second is the generic ``ellipsoid`` actor that can be used to display different
amount of ellipsoids.

We start by importing the necessary modules:

.. GENERATED FROM PYTHON SOURCE LINES 13-21

.. code-block:: Python


    import itertools

    from dipy.io.image import load_nifti
    import numpy as np

    import fury








.. GENERATED FROM PYTHON SOURCE LINES 22-24

Now, we fetch and load the data needed to display the Diffusion Tensor
Images.

.. GENERATED FROM PYTHON SOURCE LINES 24-27

.. code-block:: Python


    fury.data.fetch_viz_dmri()





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

 .. code-block:: none

    Dataset is already in place. If you want to fetch it again please first remove the folder /Users/skoudoro/.fury/dmri 

    ({'fodf.nii.gz': ('https://raw.githubusercontent.com/fury-gl/fury-data/master/dmri/fodf.nii.gz', '767ca3e4cd296e78421d83c32201b30be2d859c332210812140caac1b93d492b'), 'slice_evecs.nii.gz': ('https://raw.githubusercontent.com/fury-gl/fury-data/master/dmri/slice_evecs.nii.gz', '8843ECF3224CB8E3315B7251D1E303409A17D7137D3498A8833853C4603C6CC2'), 'slice_evals.nii.gz': ('https://raw.githubusercontent.com/fury-gl/fury-data/master/dmri/slice_evals.nii.gz', '3096B190B1146DD0EADDFECC0B4FBBD901F4933692ADD46A83F637F28B22122D'), 'roi_evecs.nii.gz': ('https://raw.githubusercontent.com/fury-gl/fury-data/master/dmri/roi_evecs.nii.gz', '89E569858A897E72C852A8F05BBCE0B21C1CA726E55508087A2DA5A38C212A17'), 'roi_evals.nii.gz': ('https://raw.githubusercontent.com/fury-gl/fury-data/master/dmri/roi_evals.nii.gz', 'F53C68CCCABF97F1326E93840A8B5CE2E767D66D692FFD955CA747FFF14EC781'), 'whole_brain_evecs.nii.gz': ('https://raw.githubusercontent.com/fury-gl/fury-data/master/dmri/whole_brain_evecs.nii.gz', '8A894F6AB404240E65451FA6D10FB5D74E2D0BDCB2A56AD6BEA38215BF787248'), 'whole_brain_evals.nii.gz': ('https://raw.githubusercontent.com/fury-gl/fury-data/master/dmri/whole_brain_evals.nii.gz', '47A73BBE68196381ED790F80F48E46AC07B699B506973FFA45A95A33023C7A77')}, '/Users/skoudoro/.fury/dmri')



.. GENERATED FROM PYTHON SOURCE LINES 28-31

The tensor ellipsoids are expressed as eigenvalues and eigenvectors which are
the decomposition of the diffusion tensor that describes the water diffusion
within a voxel.

.. GENERATED FROM PYTHON SOURCE LINES 31-39

.. code-block:: Python


    slice_evecs, _ = load_nifti(fury.data.read_viz_dmri("slice_evecs.nii.gz"))
    slice_evals, _ = load_nifti(fury.data.read_viz_dmri("slice_evals.nii.gz"))
    roi_evecs, _ = load_nifti(fury.data.read_viz_dmri("roi_evecs.nii.gz"))
    roi_evals, _ = load_nifti(fury.data.read_viz_dmri("roi_evals.nii.gz"))
    whole_brain_evecs, _ = load_nifti(fury.data.read_viz_dmri("whole_brain_evecs.nii.gz"))
    whole_brain_evals, _ = load_nifti(fury.data.read_viz_dmri("whole_brain_evals.nii.gz"))








.. GENERATED FROM PYTHON SOURCE LINES 40-48

Using tensor_slicer actor
=========================
First we must define the 3 parameters needed to use the ``tensor_slicer``
actor, which correspond to the eigenvalues, the eigenvectors, and the sphere.
For the sphere we use ``prim_sphere`` which provide vertices and triangles of
the spheres. These are labeled as 'repulsionN' with N been the number of
vertices that made up the sphere, which have a standard number of 100, 200,
and 724 vertices.

.. GENERATED FROM PYTHON SOURCE LINES 48-52

.. code-block:: Python


    vertices, faces = fury.prim_sphere(name="repulsion100", gen_faces=True)









.. GENERATED FROM PYTHON SOURCE LINES 53-55

As we need to provide a sphere object we create a class Sphere to which we
assign the values obtained from vertices and faces.

.. GENERATED FROM PYTHON SOURCE LINES 55-65

.. code-block:: Python



    class Sphere:
        def __init__(self, vertices, faces):
            self.vertices = vertices
            self.faces = faces


    sphere100 = Sphere(vertices, faces)








.. GENERATED FROM PYTHON SOURCE LINES 66-69

Now we are ready to create the ``tensor_slicer`` actor with the values of a
brain slice. We also define the scale so that the tensors are not so large
and overlap each other.

.. GENERATED FROM PYTHON SOURCE LINES 69-74

.. code-block:: Python


    tensor_slice = fury.actor.tensor_slicer(
        evals=slice_evals, evecs=slice_evecs, sphere=sphere100, scale=0.3
    )








.. GENERATED FROM PYTHON SOURCE LINES 75-77

Next, we set up a new scene to add and visualize the tensor ellipsoids
created.

.. GENERATED FROM PYTHON SOURCE LINES 77-93

.. code-block:: Python


    scene = fury.window.Scene()
    scene.background([255, 255, 255])
    scene.add(tensor_slice)

    # Create show manager
    showm = fury.window.ShowManager(scene=scene, size=(600, 600))

    # Enables/disables interactive visualization
    interactive = False

    if interactive:
        showm.start()

    fury.window.record(scene=showm.scene, size=(600, 600), out_path="tensor_slice_100.png")




.. image-sg:: /auto_examples/04_demos/images/sphx_glr_viz_dt_ellipsoids_001.png
   :alt: viz dt ellipsoids
   :srcset: /auto_examples/04_demos/images/sphx_glr_viz_dt_ellipsoids_001.png
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 94-96

If we zoom in at the scene to see with detail the tensor ellipsoids displayed
with the different spheres, we get the following results.

.. GENERATED FROM PYTHON SOURCE LINES 96-113

.. code-block:: Python


    scene.roll(10)
    scene.pitch(90)
    showm = fury.window.ShowManager(scene=scene, size=(600, 600), order_transparent=True)
    showm.scene.zoom(50)

    if interactive:
        showm.render()
        showm.start()

    fury.window.record(
        scene=showm.scene,
        out_path="tensor_slice_100_zoom.png",
        size=(600, 300),
        reset_camera=False,
    )




.. image-sg:: /auto_examples/04_demos/images/sphx_glr_viz_dt_ellipsoids_002.png
   :alt: viz dt ellipsoids
   :srcset: /auto_examples/04_demos/images/sphx_glr_viz_dt_ellipsoids_002.png
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 114-120

To render the same tensor slice using a different sphere we redefine the
vertices and faces of the sphere using prim_sphere with other sphere
specification, as 'repulsion200' or 'repulsion724'.

Now we clear the scene for the next visualization, and revert the scene
rotations.

.. GENERATED FROM PYTHON SOURCE LINES 120-126

.. code-block:: Python


    showm.scene.clear()
    showm.scene.pitch(-90)
    showm.scene.roll(-10)









.. GENERATED FROM PYTHON SOURCE LINES 127-133

Using ellipsoid actor
=====================
In order to use the ``ellipsoid`` actor to display the same tensor slice we
need to set additional parameters. For this purpose, we define a helper
function to facilitate the correct setting of the parameters before passing
them to the actor.

.. GENERATED FROM PYTHON SOURCE LINES 133-156

.. code-block:: Python



    def get_params(evecs, evals):
        # We define the centers which corresponds to the ellipsoids positions.
        valid_mask = np.abs(evecs).max(axis=(-2, -1)) > 0
        indices = np.nonzero(valid_mask)
        centers = np.asarray(indices).T

        # We need to pass the data of the axes and lengths of the ellipsoid as a
        # ndarray, so it is necessary to rearrange the data of the eigenvectors and
        # eigenvalues.
        fevecs = evecs[indices]
        fevals = evals[indices]

        # We need to define the colors of the ellipsoids following the default
        # coloring in tensor_slicer that is uses _color_fa that is a way to map
        # colors to each tensor based on the fractional anisotropy (FA) of each
        # diffusion tensor.
        colors = fury.actor._color_fa(fury.actor._fa(fevals), fevecs)

        return centers, fevecs, fevals, colors









.. GENERATED FROM PYTHON SOURCE LINES 157-159

With this we now have the values we need to define the centers, axes,
lengths, and colors of the ellipsoids.

.. GENERATED FROM PYTHON SOURCE LINES 159-162

.. code-block:: Python


    centers, evecs, evals, colors = get_params(slice_evecs, slice_evals)








.. GENERATED FROM PYTHON SOURCE LINES 163-165

Now, we can use the ``ellipsoid`` actor to create the tensor ellipsoids as
follows.

.. GENERATED FROM PYTHON SOURCE LINES 165-176

.. code-block:: Python


    tensors = fury.actor.ellipsoid(
        centers=centers, colors=colors, axes=evecs, lengths=evals, scales=0.6
    )
    showm.scene.add(tensors)

    if interactive:
        showm.start()

    fury.window.record(scene=scene, size=(600, 600), out_path="tensor_slice_sdf.png")




.. image-sg:: /auto_examples/04_demos/images/sphx_glr_viz_dt_ellipsoids_003.png
   :alt: viz dt ellipsoids
   :srcset: /auto_examples/04_demos/images/sphx_glr_viz_dt_ellipsoids_003.png
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 177-182

Thus, one can see that the same result is obtained, however there is a
difference in the visual quality and this is because the ``ellipsoid`` actor
uses raymarching technique, so the objects that are generated are smoother
since they are not made with polygons but defined by an SDF function. Next we
can see in more detail the tensor ellipsoids generated.

.. GENERATED FROM PYTHON SOURCE LINES 182-203

.. code-block:: Python


    scene.roll(10)
    scene.pitch(90)
    showm = fury.window.ShowManager(scene=scene, size=(600, 600), order_transparent=True)
    showm.scene.zoom(50)

    if interactive:
        showm.render()
        showm.start()

    fury.window.record(
        scene=showm.scene,
        out_path="tensor_slice_sdf_zoom.png",
        size=(600, 300),
        reset_camera=False,
    )

    showm.scene.clear()
    showm.scene.pitch(-90)
    showm.scene.roll(-10)




.. image-sg:: /auto_examples/04_demos/images/sphx_glr_viz_dt_ellipsoids_004.png
   :alt: viz dt ellipsoids
   :srcset: /auto_examples/04_demos/images/sphx_glr_viz_dt_ellipsoids_004.png
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 204-212

Visual quality comparison
=========================
One can see that there is a different on the visual quality of both ways of
displaying tensors and this is because ``tensor_slicer`` uses polygons while
``ellipsoid`` uses raymarching. Let's display both implementations at the
same time, so we can see this in more detail.

We first set up the required data and create the actors.

.. GENERATED FROM PYTHON SOURCE LINES 212-244

.. code-block:: Python


    mevals = np.array([1.4, 1.0, 0.35]) * 10 ** (-3)
    mevecs = np.array(
        [[2 / 3, -2 / 3, 1 / 3], [1 / 3, 2 / 3, 2 / 3], [2 / 3, 1 / 3, -2 / 3]]
    )

    evals = np.zeros((1, 1, 1, 3))
    evecs = np.zeros((1, 1, 1, 3, 3))

    evals[..., :] = mevals
    evecs[..., :, :] = mevecs

    vertices, faces = fury.prim_sphere(name="repulsion200", gen_faces=True)
    sphere200 = Sphere(vertices, faces)
    vertices, faces = fury.prim_sphere(name="repulsion724", gen_faces=True)
    sphere724 = Sphere(vertices, faces)

    tensor_100 = fury.actor.tensor_slicer(
        evals=evals, evecs=evecs, sphere=sphere100, scale=1.0
    )
    tensor_200 = fury.actor.tensor_slicer(
        evals=evals, evecs=evecs, sphere=sphere200, scale=1.0
    )
    tensor_724 = fury.actor.tensor_slicer(
        evals=evals, evecs=evecs, sphere=sphere724, scale=1.0
    )

    centers, evecs, evals, colors = get_params(evecs=evecs, evals=evals)
    tensor_sdf = fury.actor.ellipsoid(
        centers=centers, axes=evecs, lengths=evals, colors=colors, scales=2.0
    )








.. GENERATED FROM PYTHON SOURCE LINES 245-247

Next, we made use of `GridUI` which allows us to add the actors in a grid and
interact with them individually.

.. GENERATED FROM PYTHON SOURCE LINES 247-284

.. code-block:: Python


    objects = [tensor_100, tensor_200, tensor_724, tensor_sdf]
    text = [
        fury.actor.vector_text(text="Tensor 100"),
        fury.actor.vector_text(text="Tensor 200"),
        fury.actor.vector_text(text="Tensor 724"),
        fury.actor.vector_text(text="Tensor SDF"),
    ]

    grid_ui = fury.ui.GridUI(
        actors=objects,
        captions=text,
        cell_padding=0.1,
        caption_offset=(-0.7, -2.5, 0),
        dim=(1, 4),
    )

    scene = fury.window.Scene()
    scene.background([255, 255, 255])
    scene.zoom(3.5)
    scene.set_camera(position=(3.2, -20, 12), focal_point=(3.2, 0.0, 0.0))
    showm = fury.window.ShowManager(scene=scene, size=(560, 200))
    showm.scene.add(grid_ui)

    if interactive:
        showm.start()

    fury.window.record(
        scene=showm.scene,
        size=(560, 200),
        out_path="tensor_comparison.png",
        reset_camera=False,
        magnification=2,
    )

    showm.scene.clear()




.. image-sg:: /auto_examples/04_demos/images/sphx_glr_viz_dt_ellipsoids_005.png
   :alt: viz dt ellipsoids
   :srcset: /auto_examples/04_demos/images/sphx_glr_viz_dt_ellipsoids_005.png
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 285-290

Visualize a larger amount of data
=================================
With ``tensor_slicer`` is possible to visualize more than one slice using
``display_extent()``. Here we can see an example of a region of interest
(ROI) using a sphere of 100 vertices.

.. GENERATED FROM PYTHON SOURCE LINES 290-310

.. code-block:: Python


    tensor_roi = fury.actor.tensor_slicer(
        evals=roi_evals, evecs=roi_evecs, sphere=sphere100, scale=0.3
    )

    data_shape = roi_evals.shape[:3]
    tensor_roi.display_extent(0, data_shape[0], 0, data_shape[1], 0, data_shape[2])

    showm.size = (600, 600)
    showm.scene.background([0, 0, 0])
    showm.scene.add(tensor_roi)
    showm.scene.azimuth(87)

    if interactive:
        showm.start()

    fury.window.record(scene=showm.scene, size=(600, 600), out_path="tensor_roi_100.png")

    showm.scene.clear()




.. image-sg:: /auto_examples/04_demos/images/sphx_glr_viz_dt_ellipsoids_006.png
   :alt: viz dt ellipsoids
   :srcset: /auto_examples/04_demos/images/sphx_glr_viz_dt_ellipsoids_006.png
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 311-315

We can do it also with a sphere of 200 vertices, but if we try to do it with
one of 724 the visualization can no longer be rendered. In contrast, we can
visualize the ROI with the ``ellipsoid`` actor without compromising the
quality of the visualization.

.. GENERATED FROM PYTHON SOURCE LINES 315-330

.. code-block:: Python


    centers, evecs, evals, colors = get_params(roi_evecs, roi_evals)

    tensors = fury.actor.ellipsoid(
        centers=centers, colors=colors, axes=evecs, lengths=evals, scales=0.6
    )
    showm.scene.add(tensors)

    if interactive:
        showm.start()

    fury.window.record(scene=showm.scene, size=(600, 600), out_path="tensor_roi_sdf.png")

    showm.scene.clear()




.. image-sg:: /auto_examples/04_demos/images/sphx_glr_viz_dt_ellipsoids_007.png
   :alt: viz dt ellipsoids
   :srcset: /auto_examples/04_demos/images/sphx_glr_viz_dt_ellipsoids_007.png
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 331-334

In fact, although with a low performance, this actor allows us to visualize
the whole brain, which contains a much larger amount of data, to be exact
184512 tensor ellipsoids are displayed at the same time.

.. GENERATED FROM PYTHON SOURCE LINES 334-364

.. code-block:: Python


    centers, evecs, evals, colors = get_params(whole_brain_evecs, whole_brain_evals)

    # We remove all the noise around the brain to have a better visualization.
    fil = [len(set(elem)) != 1 for elem in evals]
    centers = np.array(list(itertools.compress(centers, fil)))
    colors = np.array(list(itertools.compress(colors, fil)))
    evecs = np.array(list(itertools.compress(evecs, fil)))
    evals = np.array(list(itertools.compress(evals, fil)))

    tensors = fury.actor.ellipsoid(
        centers=centers, colors=colors, axes=evecs, lengths=evals, scales=0.6
    )

    scene = fury.window.Scene()
    scene.add(tensors)
    scene.pitch(180)
    showm = fury.window.ShowManager(scene=scene, size=(600, 600))

    if interactive:
        showm.start()

    fury.window.record(
        scene=showm.scene,
        size=(600, 600),
        reset_camera=False,
        out_path="tensor_whole_brain_sdf.png",
    )

    showm.scene.clear()



.. image-sg:: /auto_examples/04_demos/images/sphx_glr_viz_dt_ellipsoids_008.png
   :alt: viz dt ellipsoids
   :srcset: /auto_examples/04_demos/images/sphx_glr_viz_dt_ellipsoids_008.png
   :class: sphx-glr-single-img






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

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


.. _sphx_glr_download_auto_examples_04_demos_viz_dt_ellipsoids.py:

.. only:: html

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

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

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

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

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


.. only:: html

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

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