With a new python package, niwidgets, we attempt to make it easier to interactively visualise neuroimaging data in jupyter notebooks. Interactive visualisations are useful both for the research process, and for the final presentation of results. It takes away the pressure to produce one illustrative snapshot of your complex, multidimensional data, and instead allows the reader to investigate and explore the data themselves.
This first release of niwidgets provides simple, one- or two-line implementations of interactive widgets in python. It provides interactive ways to slice a nifti file, and an interface to add custom interactive options such as thresholding a statistical map or changing the orientation of the plot. Combined with reports written in jupyter notebooks, this could enhance the write-up of neuroimaging studies by giving the reader the write-up, code, and interactive results all in one file.
Neuroimaging data is often highly complex. The results are often multidimensional and could be visualised in many different ways. The traditional model of presenting one snapshot of neuroimaging results only means that researchers face tough decisions on how to present their data, and can often lead to misleading figures in papers. One approach that has recently developed in the neuroimaging community is the publication of result maps - uploading the 3D results of an experiment to a repository so that readers of journal articles can investigate the results by themselves. One such example is neurovault.org Gorgolewski et al. 2015. These tools are extremely useful and provide online visualisation tools, which let readers explore the data they are reading about.
However, this still divorces the data from the article itself, as well as the code that was used to analyse the data. We wanted to provide a way for neuroscientists to provide a coherent report that includes the article, analysis code, and data alongside each other. We chose to try to implement this for jupyter notebooks. Jupyter notebooks is a language-agnostic file format that combines rich text, code, and inline results and visualisations. Given that MATLAB, python, R and bash are all supported by jupyter notebooks, and that most jupyter notebook kernels support python, a python library that visualises brain data should allow researchers to produce nice interactive combinations of writing, code and data.
We used the library ipywidgets as a basis and wrote wrapper functions that would handle the loading of neuroimaging data and the creation of interactive tools to let researchers manipulate data themselves. We used established neuroimaging packages for python - nibabel (Brett et al. 2016) and nilearn (Abraham et al. 2010) - to handle the loading of data, and used an established visualisation package for python - matplotlib - to handle the visualisation.
We first wanted to provide a simple way to explore imaging maps, so we wrote a function that simply provided three sliders, for x, y and z, and allowed people to chose a color map.
We then wanted to provide the ability to turn more sophisticated neuroimaging plots into widgets. To this end, we added the ability to provide a plotting function yourself. We so far only tested this with plotting functions from the package nilearn, as they are simple to use. When provided a custom plotting function, we tried to make niwidgets infer basic interactive features about the plot, such as whether it supports interactive x-, y-, and z-coordinates. We also tried to enable custom colormaps for all plots, which could be useful to prevent issues around categorical colormaps (Hawkins 2016) or colormaps unsuited for colorblind readers (Albrecht 2010).
We produced a python package called niwidgets. So far, the package provides one class (NiWidget). To initialise this class, only one input is needed: the path to a nifti file.
The NiWidget class provides one method at the moment (nifti_plotter). This method can be called without any input to provide a default function, and with a custom plotting function as input to provide more versatile plots.
In [ ]:
from niwidgets import NiWidget
The default function produces a widget that allows the reader to choose any position within the image using three sliders (x, y and z). It also allows the reader to choose any of the colormaps that are part of the matplotlib package (Fig. 1). Creating this widget only requires two lines of code: 1) Initialise the class using NiWidget('/path/to/file') and 2) Create the widget using .nifti_plotter()
In [ ]:
from niwidgets import examplet1 # this is an example T1 dataset
my_widget = NiWidget(examplet1)
my_widget.nifti_plotter()
When the nifti_plotter() method is called with the optional keyword argument plotting_func defined, it produces a plot that uses the provided function. We have tested this primarily with nilearn.plotting functions, but will test it for other functions in the future, too. We attempted to "coerce" these functions to support custom colormaps, and provide the same selection of colormaps we do for the default plotting function. We also tried to detect whether the plotting function supports the specification of x/y/z coordinates, and if so implement interactive sliders for them. An example of this is the nilearn.plotting.plot_glass_brain function (Fig. 2).
In [ ]:
from niwidgets import examplezmap # this is an example statistical map from neurosynth
import nilearn.plotting as nip
my_widget = NiWidget(examplezmap)
my_widget.nifti_plotter(plotting_func=nip.plot_glass_brain, # custom plot function
threshold=(0.0, 6.0, 0.01), # custom slider
display_mode=['ortho','xz']) # custom drop-down menu
The most important limitation of niwidgets at the moment is that it only supports the illustration of volume imaging data in nifti files. In the future, we would like to also provide interactives for surface projections, such as those created with the python package pysurf.
Additionally, for niwidgets to work, the reader has to run the notebook with their own installation of Ipython. While it is possible to do this remotely using the free service mybinder.org, it would be even better if widgets worked when notebooks are converted to static webpages. Notebooks are already viewable as static web pages on Github, a popular software repository, but dynamic widgets are currently not supported. However, this is in the process of being implemented by the ipywidget package maintainers, so this limitation may soon disappear.
Lastly, the niwidgets package is not bug-free enough for a stable release yet. There are still many issues around implementing custom interactives with a diverse range of plotting functions (such as the nilearn.plotting.plot_stat_map function), and it will require more work to be stable. We encourage the opening of issues on the niwidgets github repository, as well as pull requests for the implementation of new features or fixing of bugs.