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

.. only:: html

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

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

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

.. _sphx_glr_gallery_scene_volume.py:


Volume Rendering
================

Example volume rendering

Controls:

* 1  - toggle camera between first person (fly), regular 3D (turntable) and
       arcball
* 2  - toggle between volume rendering methods
* 3  - toggle between stent-CT / brain-MRI image
* 4  - toggle between colormaps
* 5  - toggle between interpolation methods
* 0  - reset cameras
* [] - decrease/increase isosurface threshold

With fly camera:

* WASD or arrow keys - move around
* SPACE - brake
* FC - move up-down
* IJKL or mouse - look around

.. GENERATED FROM PYTHON SOURCE LINES 32-169



.. image-sg:: /gallery/scene/images/sphx_glr_volume_001.png
   :alt: volume
   :srcset: /gallery/scene/images/sphx_glr_volume_001.png
   :class: sphx-glr-single-img


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

 Out:

 .. code-block:: none

    Downloading data from https://raw.githubusercontent.com/vispy/demo-data/main/brain/mri.npz (3.9 MB)

    [                                        ] 1.60843 | downloading   
    [.                                       ] 3.21685 / downloading   
    [.                                       ] 4.82528 - downloading   
    [..                                      ] 6.43371 \ downloading   
    [...                                     ] 8.04213 | downloading   
    [...                                     ] 9.65056 / downloading   
    [....                                    ] 11.25899 - downloading   
    [.....                                   ] 12.86741 \ downloading   
    [.....                                   ] 14.47584 | downloading   
    [......                                  ] 16.08427 / downloading   
    [.......                                 ] 17.69269 - downloading   
    [.......                                 ] 19.30112 \ downloading   
    [........                                ] 20.90955 | downloading   
    [.........                               ] 22.51797 / downloading   
    [.........                               ] 24.12640 - downloading   
    [..........                              ] 25.73483 \ downloading   
    [..........                              ] 27.34325 | downloading   
    [...........                             ] 28.95168 / downloading   
    [............                            ] 30.56010 - downloading   
    [............                            ] 32.16853 \ downloading   
    [.............                           ] 33.77696 | downloading   
    [..............                          ] 35.38538 / downloading   
    [..............                          ] 36.99381 - downloading   
    [...............                         ] 38.60224 \ downloading   
    [................                        ] 40.21066 | downloading   
    [................                        ] 41.81909 / downloading   
    [.................                       ] 43.42752 - downloading   
    [..................                      ] 45.03594 \ downloading   
    [..................                      ] 46.64437 | downloading   
    [...................                     ] 48.25280 / downloading   
    [...................                     ] 49.86122 - downloading   
    [....................                    ] 51.46965 \ downloading   
    [.....................                   ] 53.07808 | downloading   
    [.....................                   ] 54.68650 / downloading   
    [......................                  ] 56.29493 - downloading   
    [.......................                 ] 57.90336 \ downloading   
    [.......................                 ] 59.51178 | downloading   
    [........................                ] 61.12021 / downloading   
    [.........................               ] 62.72864 - downloading   
    [.........................               ] 64.33706 \ downloading   
    [..........................              ] 65.94549 | downloading   
    [...........................             ] 67.55392 / downloading   
    [...........................             ] 69.16234 - downloading   
    [............................            ] 70.77077 \ downloading   
    [............................            ] 72.37920 | downloading   
    [.............................           ] 73.98762 / downloading   
    [..............................          ] 75.59605 - downloading   
    [..............................          ] 77.20448 \ downloading   
    [...............................         ] 78.81290 | downloading   
    [................................        ] 80.42133 / downloading   
    [................................        ] 82.02976 - downloading   
    [.................................       ] 83.63818 \ downloading   
    [..................................      ] 85.24661 | downloading   
    [..................................      ] 86.85503 / downloading   
    [...................................     ] 88.46346 - downloading   
    [....................................    ] 90.07189 \ downloading   
    [....................................    ] 91.68031 | downloading   
    [.....................................   ] 93.28874 / downloading   
    [.....................................   ] 94.89717 - downloading   
    [......................................  ] 96.50559 \ downloading   
    [....................................... ] 98.11402 | downloading   
    [....................................... ] 99.72245 / downloading   
    [........................................] 100.00000 - downloading   
    File saved as /tmp/tmp.NVC9tXepCc/.vispy/data/brain/mri.npz.







|

.. code-block:: default


    from itertools import cycle

    import numpy as np

    from vispy import app, scene, io
    from vispy.color import get_colormaps, BaseColormap
    from vispy.visuals.transforms import STTransform

    # Read volume
    vol1 = np.load(io.load_data_file('volume/stent.npz'))['arr_0']
    vol2 = np.load(io.load_data_file('brain/mri.npz'))['data']
    vol2 = np.flipud(np.rollaxis(vol2, 1))

    # Prepare canvas
    canvas = scene.SceneCanvas(keys='interactive', size=(800, 600), show=True)
    canvas.measure_fps()

    # Set up a viewbox to display the image with interactive pan/zoom
    view = canvas.central_widget.add_view()

    # Create the volume visuals, only one is visible
    volume1 = scene.visuals.Volume(vol1, parent=view.scene, threshold=0.225)
    volume1.transform = scene.STTransform(translate=(64, 64, 0))
    volume2 = scene.visuals.Volume(vol2, parent=view.scene, threshold=0.2)
    volume2.visible = False

    # Create three cameras (Fly, Turntable and Arcball)
    fov = 60.
    cam1 = scene.cameras.FlyCamera(parent=view.scene, fov=fov, name='Fly')
    cam2 = scene.cameras.TurntableCamera(parent=view.scene, fov=fov,
                                         name='Turntable')
    cam3 = scene.cameras.ArcballCamera(parent=view.scene, fov=fov, name='Arcball')
    view.camera = cam2  # Select turntable at first

    # Create an XYZAxis visual
    axis = scene.visuals.XYZAxis(parent=view)
    s = STTransform(translate=(50, 50), scale=(50, 50, 50, 1))
    affine = s.as_matrix()
    axis.transform = affine


    # create colormaps that work well for translucent and additive volume rendering
    class TransFire(BaseColormap):
        glsl_map = """
        vec4 translucent_fire(float t) {
            return vec4(pow(t, 0.5), t, t*t, max(0, t*1.05 - 0.05));
        }
        """


    class TransGrays(BaseColormap):
        glsl_map = """
        vec4 translucent_grays(float t) {
            return vec4(t, t, t, t*0.05);
        }
        """

    # Setup colormap iterators
    opaque_cmaps = cycle(get_colormaps())
    translucent_cmaps = cycle([TransFire(), TransGrays()])
    opaque_cmap = next(opaque_cmaps)
    translucent_cmap = next(translucent_cmaps)

    interp_methods = cycle(volume1.interpolation_methods)
    interp = next(interp_methods)


    # Implement axis connection with cam2
    @canvas.events.mouse_move.connect
    def on_mouse_move(event):
        if event.button == 1 and event.is_dragging:
            axis.transform.reset()

            axis.transform.rotate(cam2.roll, (0, 0, 1))
            axis.transform.rotate(cam2.elevation, (1, 0, 0))
            axis.transform.rotate(cam2.azimuth, (0, 1, 0))

            axis.transform.scale((50, 50, 0.001))
            axis.transform.translate((50., 50.))
            axis.update()


    # Implement key presses
    @canvas.events.key_press.connect
    def on_key_press(event):
        global opaque_cmap, translucent_cmap
        if event.text == '1':
            cam_toggle = {cam1: cam2, cam2: cam3, cam3: cam1}
            view.camera = cam_toggle.get(view.camera, cam2)
            print(view.camera.name + ' camera')
            if view.camera is cam2:
                axis.visible = True
            else:
                axis.visible = False
        elif event.text == '2':
            methods = ['mip', 'translucent', 'iso', 'additive']
            method = methods[(methods.index(volume1.method) + 1) % 4]
            print("Volume render method: %s" % method)
            cmap = opaque_cmap if method in ['mip', 'iso'] else translucent_cmap
            volume1.method = method
            volume1.cmap = cmap
            volume2.method = method
            volume2.cmap = cmap
        elif event.text == '3':
            volume1.visible = not volume1.visible
            volume2.visible = not volume1.visible
        elif event.text == '4':
            if volume1.method in ['mip', 'iso']:
                cmap = opaque_cmap = next(opaque_cmaps)
            else:
                cmap = translucent_cmap = next(translucent_cmaps)
            volume1.cmap = cmap
            volume2.cmap = cmap
        elif event.text == '5':
            interp = next(interp_methods)
            volume1.interpolation = interp
            volume2.interpolation = interp
            print(f"Interpolation method: {interp}")
        elif event.text == '0':
            cam1.set_range()
            cam3.set_range()
        elif event.text != '' and event.text in '[]':
            s = -0.025 if event.text == '[' else 0.025
            volume1.threshold += s
            volume2.threshold += s
            th = volume1.threshold if volume1.visible else volume2.threshold
            print("Isosurface threshold: %0.3f" % th)

    # for testing performance
    # @canvas.connect
    # def on_draw(ev):
    # canvas.update()

    if __name__ == '__main__':
        print(__doc__)
        app.run()


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

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


.. _sphx_glr_download_gallery_scene_volume.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: volume.py <volume.py>`



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

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


.. only:: html

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

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