Anatomist notebook extension demo

This notebook demonstrates the notebook variant of Anatomist. It runs inside Jupyter notebook. Paths in the demo assume that the notebook is run inside a casa-distro container, and a recent build in python3 (jupyter extensions have been added only in python3 in this container).

[1]:
import os
from soma import aims
doc = aims.carto.Paths.findResourceFile('doc/pyanatomist-5.1/sphinx/pyanatomist_notebook.html')
casa = os.environ.get('CASA_HOST_DIR')
if casa:  # we are in a virtual container, replace with host path
    doc = os.sep.join(doc.split(os.sep)[-4:])
    doc = os.path.join(casa, doc)
print('Doc is available at the following address:')
print('file://' + doc)
print('You can copy it and paste it in your web browser.')
Doc is available at the following address:
file:///home/brainvisa/web-build/doc/pyanatomist-5.1/sphinx/pyanatomist_notebook.html
You can copy it and paste it in your web browser.

First download and install a small dataset, if needed:

[2]:
dl_url = 'https://brainvisa.info/download/data/morpho_demo.tar.bz2'
from soma import aims
install_dir = os.path.join(aims.carto.Paths.globalShared(), 'morpho_demo')
temp_dirs = []
if os.path.exists(install_dir):
    print('the data directory already exists. Assuming it is OK.')
else:
    try:
        os.makedirs(install_dir)
    except:
        # maybe we don't have write permission in the directory
        # try again in a temp directory
        install_dir = tempfile.mkdtemp(prefix='ana_notebook_demo')
        temp_dirs.append(install_dir)

    # download demo data
    from six.moves.urllib.request import urlopen
    import tempfile
    import tarfile

    tmp_dl = tempfile.mkstemp(suffix='.tar.bz2')
    os.close(tmp_dl[0])
    with urlopen(dl_url) as f:
        with open(tmp_dl[1], 'wb') as g:
            g.write(f.read())
    # extract the archive
    with tarfile.open(tmp_dl[1], 'r') as tf:
        tf.extractall(install_dir)
print('using data in:', install_dir)
os.chdir(install_dir)
the data directory already exists. Assuming it is OK.
using data in: /casa/host/build/build_files/anatomist-gpl/pyanatomist/../../../share/morpho_demo

The API is exactly the same as the “regular” Anatomist:

[3]:
import anatomist.notebook as ana
a = ana.Anatomist()
print(a.headless_info.__dict__)
VirtualGL found.
VirtualGL should work.
Running through VirtualGL + Xvfb: this is optimal.
global modules: /casa/host/build/build_files/anatomist-gpl/pyanatomist/../../../share/anatomist-5.1/python_plugins
home   modules: /casa/home/.anatomist/python_plugins
loading module meshsplit
loading module modelGraphs
loading module histogram
loading module bundles_split_by_cortical_regions
loading module palettecontrols
loading module paletteViewer
loading module ana_image_math
Anatomist started.
loading module simple_controls
loading module bsa_proba
loading module selection
loading module bundles_small_brains
loading module anacontrolmenu
loading module gradientpalette
loading module foldsplit
loading module profilewindow
loading module save_resampled
loading module volumepalettes
loading module gltf_io
all python modules loaded
Anatomist started.
{'xvfb': <Popen: returncode: None args: ['Xvfb', '-screen', '0', '1280x1024x24', '+ex...>, 'original_display': ':0', 'display': 1, 'glx': 2, 'virtualgl': True, 'headless': True, 'mesa': False, 'qtapp': None}
[4]:
mri = a.loadObject('demo/morphee/t1mri/default_acquisition/morphee.nii.gz')
seg = a.loadObject('demo/morphee/t1mri/default_acquisition/default_analysis/segmentation/Lgrey_white_morphee.nii.gz')
w1 = a.createWindow('Axial')
w2 = a.createWindow('Coronal')
mri.addInWindows([w1, w2])
seg.setPalette('Blue-Red-fusion')
w2.addObjects(seg)
w1.moveLinkedCursor([70., 120., 75.])

As you will note, views here are interactive and are displaying standard Anatomist views. 3D hardware is used when possible as in the headless variant of Anatomist. Displaying is a blit slower (thus less smooth) however because rendering is performed on server side, then compressed in JPEG, and transfered to the web browser.

“expensive” renderings such as Volume Rendering can be done without more overhead:

[5]:
fus2 = a.fusionObjects([mri, seg], method='Fusion2DMethod')
a.execute('TexturingParams', objects=[fus2], texture_index=1, mode='linear_A_if_B_white')
vol_render = a.fusionObjects([fus2], method='VolumeRenderingFusionMethod')
vol_render.setPalette(minVal=0.25, maxVal=1.3)
cut_vr = a.fusionObjects([vol_render], method='FusionClipMethod')
w3 = a.createWindow('3D')
w3.addObjects(cut_vr)
w3.setControl('CutControl')

The view above is also interactive (use middle button to rotate, shift+middle to orient the cut plane, ctrl+middle to shift it)

Other kind of windows can be displayed also, but are not refreshed as often as needed. Only user input triggers updates (but moving the mouse focus in/out is enough):

[6]:
browser = a.createWindow('Browser')
hist = a.createWindow('Matplotlib-histogram')
mri.addInWindows([browser, hist])
No handles with labels found to put in legend.

Of course, meshes can also be displayed (as well as all objects supported by Anatomist):

[7]:
mesh_l = a.loadObject('demo/morphee/t1mri/default_acquisition/default_analysis/segmentation/mesh/morphee_Lhemi.gii')
mesh_r = a.loadObject('demo/morphee/t1mri/default_acquisition/default_analysis/segmentation/mesh/morphee_Rwhite.gii')
nomenclature = a.loadObject(aims.carto.Paths.findResourceFile('nomenclature/hierarchy/sulcal_root_colors.hie'))
sulci_r = a.loadObject('demo/morphee/t1mri/default_acquisition/default_analysis/folds/3.1/default_session_auto/Rmorphee_default_session_auto.arg')
mesh_r.setMaterial(diffuse=[0.7, 1., 0.7, 1.])
mesh_cut = a.fusionObjects([mesh_l, mri], method='FusionCutMeshMethod')
w4 = a.createWindow('3D')
w4.addObjects([mesh_cut, mesh_r, sulci_r])
No handles with labels found to put in legend.

It is also possible to embed 3D views only (without sliders and buttons):

[8]:
view = a.createWindow('3D', only_3d=True)
view.addObjects([mesh_cut, mri])
view.camera(view_quaternion=[0.445286393165588,  0.11355659365654, 0.125850886106491, 0.879196524620056])
No handles with labels found to put in legend.

or with sliders but without buttons (as in the regular anatomist):

[9]:
w5 = a.createWindow('3D', no_decoration=True)
w5.addObjects([mesh_cut, mri])
w5.camera(view_quaternion=[0.445286393165588,  0.11355659365654, 0.125850886106491, 0.879196524620056])
No handles with labels found to put in legend.

If needed, we may cleanup the data installed temporarily…

[10]:
import shutil
for d in temp_dirs:
    shutil.rmtree(d)