.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/04_demos/viz_fiber_odf.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_04_demos_viz_fiber_odf.py: ==================================== Brain Fiber ODF Visualisation ==================================== This example demonstrate how to create a simple viewer for fiber orientation distribution functions (ODF) using fury's odf_slicer. .. GENERATED FROM PYTHON SOURCE LINES 9-21 .. code-block:: Python import nibabel as nib # First, we import some useful modules and methods. import numpy as np from dipy.data import get_sphere from dipy.reconst.shm import sh_to_sf_matrix from fury import actor, ui, window from fury.data import fetch_viz_dmri, fetch_viz_icons, read_viz_dmri from fury.utils import fix_winding_order .. GENERATED FROM PYTHON SOURCE LINES 22-24 Here, we fetch and load the fiber ODF volume to display. The ODF are expressed as spherical harmonics (SH) coefficients in a 3D grid. .. GENERATED FROM PYTHON SOURCE LINES 24-32 .. code-block:: Python fetch_viz_dmri() fetch_viz_icons() fodf_img = nib.load(read_viz_dmri('fodf.nii.gz')) sh = fodf_img.get_fdata() affine = fodf_img.affine grid_shape = sh.shape[:-1] .. 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 Data size is approximately 12KB Dataset is already in place. If you want to fetch it again please first remove the folder /Users/skoudoro/.fury/icons .. GENERATED FROM PYTHON SOURCE LINES 33-36 We then define a low resolution sphere used to visualize SH coefficients as spherical functions (SF) as well as a matrix `B_low` to project SH onto the sphere. .. GENERATED FROM PYTHON SOURCE LINES 36-39 .. code-block:: Python sphere_low = get_sphere('repulsion100') B_low = sh_to_sf_matrix(sphere_low, 8, return_inv=False) .. GENERATED FROM PYTHON SOURCE LINES 40-42 Now, we create a slicer for each orientation to display a slice in the middle of the volume and we add them to a `scene`. .. GENERATED FROM PYTHON SOURCE LINES 42-107 .. code-block:: Python # Change these values to test various parameters combinations. scale = 0.5 norm = False colormap = None radial_scale = True opacity = 1.0 global_cm = False # ODF slicer for axial slice odf_actor_z = actor.odf_slicer( sh, affine=affine, sphere=sphere_low, scale=scale, norm=norm, radial_scale=radial_scale, opacity=opacity, colormap=colormap, global_cm=global_cm, B_matrix=B_low, ) # ODF slicer for coronal slice odf_actor_y = actor.odf_slicer( sh, affine=affine, sphere=sphere_low, scale=scale, norm=norm, radial_scale=radial_scale, opacity=opacity, colormap=colormap, global_cm=global_cm, B_matrix=B_low, ) odf_actor_y.display_extent( 0, grid_shape[0] - 1, grid_shape[1] // 2, grid_shape[1] // 2, 0, grid_shape[2] - 1 ) # ODF slicer for sagittal slice odf_actor_x = actor.odf_slicer( sh, affine=affine, sphere=sphere_low, scale=scale, norm=norm, radial_scale=radial_scale, opacity=opacity, colormap=colormap, global_cm=global_cm, B_matrix=B_low, ) odf_actor_x.display_extent( grid_shape[0] // 2, grid_shape[0] // 2, 0, grid_shape[1] - 1, 0, grid_shape[2] - 1 ) scene = window.Scene() scene.add(odf_actor_z) scene.add(odf_actor_y) scene.add(odf_actor_x) show_m = window.ShowManager(scene, reset_camera=True, size=(1200, 900)) .. GENERATED FROM PYTHON SOURCE LINES 108-110 Now that we have a `ShowManager` containing our slicer, we can go on and configure our UI for changing the slices to visualize. .. GENERATED FROM PYTHON SOURCE LINES 110-134 .. code-block:: Python line_slider_z = ui.LineSlider2D( min_value=0, max_value=grid_shape[2] - 1, initial_value=grid_shape[2] / 2, text_template='{value:.0f}', length=140, ) line_slider_y = ui.LineSlider2D( min_value=0, max_value=grid_shape[1] - 1, initial_value=grid_shape[1] / 2, text_template='{value:.0f}', length=140, ) line_slider_x = ui.LineSlider2D( min_value=0, max_value=grid_shape[0] - 1, initial_value=grid_shape[0] / 2, text_template='{value:.0f}', length=140, ) .. GENERATED FROM PYTHON SOURCE LINES 135-137 We also define a high resolution sphere to demonstrate the capability to dynamically change the sphere used for SH to SF projection. .. GENERATED FROM PYTHON SOURCE LINES 137-144 .. code-block:: Python sphere_high = get_sphere('symmetric362') # We fix the order of the faces' three vertices to a clockwise winding. This # ensures all faces have a normal going away from the center of the sphere. sphere_high.faces = fix_winding_order(sphere_high.vertices, sphere_high.faces, True) B_high = sh_to_sf_matrix(sphere_high, 8, return_inv=False) .. GENERATED FROM PYTHON SOURCE LINES 145-146 We add a combobox for choosing the sphere resolution during execution. .. GENERATED FROM PYTHON SOURCE LINES 146-153 .. code-block:: Python sphere_dict = { 'Low resolution': (sphere_low, B_low), 'High resolution': (sphere_high, B_high), } combobox = ui.ComboBox2D(items=list(sphere_dict)) scene.add(combobox) .. GENERATED FROM PYTHON SOURCE LINES 154-155 Here we will write callbacks for the sliders and combo box and register them. .. GENERATED FROM PYTHON SOURCE LINES 155-184 .. code-block:: Python def change_slice_z(slider): i = int(np.round(slider.value)) odf_actor_z.slice_along_axis(i) def change_slice_y(slider): i = int(np.round(slider.value)) odf_actor_y.slice_along_axis(i, 'yaxis') def change_slice_x(slider): i = int(np.round(slider.value)) odf_actor_x.slice_along_axis(i, 'xaxis') def change_sphere(combobox): sphere, B = sphere_dict[combobox.selected_text] odf_actor_x.update_sphere(sphere.vertices, sphere.faces, B) odf_actor_y.update_sphere(sphere.vertices, sphere.faces, B) odf_actor_z.update_sphere(sphere.vertices, sphere.faces, B) line_slider_z.on_change = change_slice_z line_slider_y.on_change = change_slice_y line_slider_x.on_change = change_slice_x combobox.on_change = change_sphere .. GENERATED FROM PYTHON SOURCE LINES 185-186 We then add labels for the sliders and position them inside a panel. .. GENERATED FROM PYTHON SOURCE LINES 186-219 .. code-block:: Python def build_label(text): label = ui.TextBlock2D() label.message = text label.font_size = 18 label.font_family = 'Arial' label.justification = 'left' label.bold = False label.italic = False label.shadow = False label.background_color = (0, 0, 0) label.color = (1, 1, 1) return label line_slider_label_z = build_label(text='Z Slice') line_slider_label_y = build_label(text='Y Slice') line_slider_label_x = build_label(text='X Slice') panel = ui.Panel2D(size=(300, 200), color=(1, 1, 1), opacity=0.1, align='right') panel.center = (1030, 120) panel.add_element(line_slider_label_x, (0.1, 0.75)) panel.add_element(line_slider_x, (0.38, 0.75)) panel.add_element(line_slider_label_y, (0.1, 0.55)) panel.add_element(line_slider_y, (0.38, 0.55)) panel.add_element(line_slider_label_z, (0.1, 0.35)) panel.add_element(line_slider_z, (0.38, 0.35)) show_m.scene.add(panel) .. GENERATED FROM PYTHON SOURCE LINES 220-226 Then, we can render all the widgets and everything else in the screen and start the interaction using ``show_m.start()``. However, if you change the window size, the panel will not update its position properly. The solution to this issue is to update the position of the panel using its ``re_align`` method every time the window size changes. .. GENERATED FROM PYTHON SOURCE LINES 226-238 .. code-block:: Python size = scene.GetSize() def win_callback(obj, _event): global size if size != obj.GetSize(): size_old = size size = obj.GetSize() size_change = [size[0] - size_old[0], 0] panel.re_align(size_change) .. GENERATED FROM PYTHON SOURCE LINES 239-241 Finally, please set the following variable to ``True`` to interact with the datasets in 3D. .. GENERATED FROM PYTHON SOURCE LINES 241-253 .. code-block:: Python interactive = False if interactive: show_m.add_window_callback(win_callback) show_m.render() show_m.start() else: window.record( scene, out_path='odf_slicer_3D.png', size=(1200, 900), reset_camera=False ) del show_m .. image-sg:: /auto_examples/04_demos/images/sphx_glr_viz_fiber_odf_001.png :alt: viz fiber odf :srcset: /auto_examples/04_demos/images/sphx_glr_viz_fiber_odf_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 1.238 seconds) .. _sphx_glr_download_auto_examples_04_demos_viz_fiber_odf.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: viz_fiber_odf.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: viz_fiber_odf.py ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_