Source code for navis.conversion.wrappers

#    This script is part of navis (
#    Copyright (C) 2018 Philipp Schlegel
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    GNU General Public License for more details.

import trimesh as tm
import numpy as np

from typing import Union, Optional
from typing_extensions import Literal

from .. import core, config, utils
from .converters import (neuron2voxels, mesh2skeleton, tree2meshneuron,
from .meshing import voxels2mesh

logger = config.get_logger(__name__)

[docs] @utils.map_neuronlist(desc='Skeletonizing', allow_parallel=True) def skeletonize(x: Union['core.MeshNeuron', 'core.Dotprops', np.ndarray], **kwargs): """Turn neuron into skeleton. Currently, we can only skeletonize meshes, dotprops and point clouds but are looking into ways to also do it for ``VoxelNeurons``. For meshes, this function is a thin-wrapper for `skeletor`. It uses sensible defaults for neurons but if you want to fine-tune your skeletons you should look into using `skeletor` directly. Parameters ---------- x : MeshNeuron | trimesh.Trimesh | Dotprops Mesh(es) to skeletonize. Note that the quality of the results very much depends on the mesh, so it might be worth doing some pre-processing (see below). **kwargs Keyword arguments are passed through to the respective converters: - meshes: :func:`navis.conversion.mesh2skeleton` - dotprops and point clouds: :func:`navis.conversion.points2skeleton` Returns ------- skeleton : navis.TreeNeuron For meshes, this has a `.vertex_map` attribute that maps each vertex in the input mesh to a skeleton node ID. See Also -------- :func:`navis.drop_fluff` Use this if your mesh has lots of tiny free floating bits to reduce noise and speed up skeletonization. Examples -------- # Skeletonize a mesh >>> import navis >>> # Get a mesh neuron >>> n = navis.example_neurons(1, kind='mesh') >>> # Convert to skeleton >>> sk = navis.skeletonize(n) >>> # Mesh vertex indices to node IDs map >>> sk.vertex_map # doctest: +SKIP array([938, 990, 990, ..., 39, 234, 234]) # Skeletonize dotprops (i.e. point-clouds) >>> import navis >>> # Get a skeleton and turn into dotprops >>> dp = navis.make_dotprops(navis.example_neurons(1)) >>> # Turn back into a skeleton >>> sk = navis.skeletonize(dp) """ if isinstance(x, (core.MeshNeuron, tm.Trimesh)): return mesh2skeleton(x, **kwargs) elif isinstance(x, (core.Dotprops, )): sk = points2skeleton(x.points, **kwargs) for attr in ('id', 'units', 'name'): if hasattr(x, attr): setattr(sk, attr, getattr(x, attr)) return sk elif isinstance(x, np.ndarray): return points2skeleton(x.points, **kwargs) raise TypeError(f'Unable to skeletonize data of type {type(x)}')
[docs] @utils.map_neuronlist(desc='Voxelizing', allow_parallel=True) def voxelize(x: 'core.BaseNeuron', pitch: Union[list, tuple, float], bounds: Optional[list] = None, counts: bool = False, vectors: bool = False, alphas: bool = False, smooth: int = 0) -> 'core.VoxelNeuron': """Turn neuron into voxels. Parameters ---------- x : TreeNeuron | MeshNeuron | Dotprops Neuron(s) to voxelize. Uses the neurons' nodes, vertices and points, respectively. pitch : float | iterable thereof Side length(s) voxels. Can be isometric (float) or an iterable of dimensions in (x, y, z). bounds : (3, 2) or (2, 3) array, optional Boundaries [in units of `x`] for the voxel grid. If not provided, will use ``x.bbox``. counts : bool If True, voxel grid will have point counts for values instead of just True/False. vectors : bool If True, will also attach a vector field as `.vectors` property. alphas : bool If True, will also return a grid with alpha values as `.alpha` property. smooth : int If non-zero, will apply a Gaussian filter with ``smooth`` as ``sigma``. Returns ------- VoxelNeuron Has the voxel grid as `.grid` and (optionally) `.vectors` and `.alphas` properties. `.grid` data type depends on settings: - default = bool (i.e. True/False) - if ``counts=True`` = integer - if ``smooth=True`` = float Empty voxels will have vector (0, 0, 0) and alpha 0. Also note that data tables (e.g. `connectors`) are not carried over from the input neuron. Examples -------- >>> import navis >>> # Get a skeleton >>> n = navis.example_neurons(1) >>> # Convert to voxel neuron >>> vx = navis.voxelize(n, pitch='5 microns') """ if isinstance(x, (core.TreeNeuron, core.MeshNeuron, core.Dotprops)): return neuron2voxels(x, pitch=pitch, bounds=bounds, counts=counts, vectors=vectors, alphas=alphas, smooth=smooth) raise TypeError(f'Unable to voxelize data of type {type(x)}')
[docs] @utils.map_neuronlist(desc='Meshing', allow_parallel=True) def mesh(x: Union['core.VoxelNeuron', np.ndarray, 'core.TreeNeuron'], **kwargs) -> Union[tm.Trimesh, 'core.MeshNeuron']: """Generate mesh from object(s). VoxelNeurons or (N, 3) arrays of voxel coordinates will be meshed using a marching cubes algorithm. TreeNeurons will be meshed by creating cylinders using the radii. Parameters ---------- x : VoxelNeuron | (N, 3) np.array | TreeNeuron Object to mesh. See notes above. **kwargs Keyword arguments are passed through to the respective converters: :func:`navis.conversion.voxels2mesh` and :func:`navis.conversion.tree2meshneuron`, respectively. Returns ------- mesh : trimesh.Trimesh | MeshNeuron Returns a trimesh or MeshNeuron depending on the input. Data tables (e.g. `connectors`) are not carried over from input neuron. """ if isinstance(x, core.VoxelNeuron) or (isinstance(x, np.ndarray) and x.ndims == 2 and x.shape[1] == 3): return voxels2mesh(x, **kwargs) elif isinstance(x, core.TreeNeuron): return tree2meshneuron(x, **kwargs) raise TypeError(f'Unable to create mesh from data of type {type(x)}')