navis-org / navis

Python library for analysis of neuroanatomical data.
https://navis-org.github.io/navis/
GNU General Public License v3.0
83 stars 33 forks source link

Improve plotting #157

Closed schlegelp closed 3 months ago

schlegelp commented 3 months ago

This PR represents a medium-sized rework of the plotting system.

First up the unpleasant part as there are a few (minor) breaking changes:

Now to the fun bits:

Octarine

This PR adds Octarine as the default backend for 3d plotting from terminal (it also works in Jupyter). With it comes a smart(er) backend selection where we check which backends are available and choose the nominally "best". For non-Jupyter the order is: Octarine > Vispy > plotly. For Jupyter the order is currently plotly > Octarine > k3d. The latter may still change since this PR also makes the internal navis.Viewer Jupyter-capable.

pip install navis[all] will now install all supported backends. The minimal install pip install navis installs only matplotlib.

Plot 2D style

The default style for plot2d() has been a bit of an eyesore and I noticed that in my own code I often heavily tinker with the defaults. With this PR we're changing the defaults so we get nice looking plots off the bat. Here are two examples:

import navis
nl = navis.example_neurons()
fig, ax = navis.plot2d(nl, method='2d', view=('x', '-z'))

plot2d_comp

import navis
nl = navis.example_neurons()
fig, ax = navis.plot2d(nl, method='3d', view=('x', '-z'))

plot2d_comp3d

These are the major changes:

To account for the new radius=True default, the color_by and shade_by parameters should now also work when plotting skeletons with radius=True (i.e. we internally map the skeleton node colors onto the derived mesh's vertices).

Parameter validation

Previously, both plot2d and plot3d accepted a vague number of keyword arguments, some of which were documented while others were not. Both plotting functions still accept keyword arguments but this PR introduces Python data classes to validate parameters. Here is a quick example of what this looks like:

@dataclass
class Matplotlib2dSettings(BasePlottingSettings):
    """Additional plotting parameters for Matplotlib 2d backend."""

    method: Literal["2d", "3d", "3d_complex"] = "2d"
    group_neurons: bool = False
    autoscale: bool = True
    orthogonal: bool = True
    ...

settings = Matplotlib2dSettings().update_settings(**kwargs)

Advantages:

It's still not perfect because some features are backend-specific but definitely better than before.

Misc

TODOs

schlegelp commented 3 months ago

As expected, adding a new backend has played havoc with the test suite but all tests are passing now. Visualisation-related testing is still a bit of a hack and relies mostly on the tutorial notebooks. For example, not every functionality is tested with every backend. I don't think I want to address that in this PR.

A couple more test-related notes:

  1. This PR drops "no igraph" from the matrix since igraph is an implicit hard dependency through skeletor by now
  2. I ended up having to skip the test_lookupdistdotbuilder_builds tests because they started hanging for no good reason. We've had issues with those and the use of threads in the past. Need to investigate.