Skip to content

Commit

Permalink
Improve documentation of the API (#113)
Browse files Browse the repository at this point in the history
  • Loading branch information
adrien-berchet committed Mar 30, 2023
1 parent 71dfd31 commit 70f9e42
Show file tree
Hide file tree
Showing 16 changed files with 398 additions and 295 deletions.
1 change: 1 addition & 0 deletions doc/source/api.rst
Expand Up @@ -18,6 +18,7 @@ API
neuror.utils
neuror.axon
neuror.main
neuror.exceptions
neuror.cut_plane.cut_leaves
neuror.cut_plane.detection
neuror.cut_plane.legacy_detection
Expand Down
22 changes: 21 additions & 1 deletion doc/source/conf.py
Expand Up @@ -28,6 +28,7 @@
'sphinx_autorun',
'sphinx.ext.autodoc',
'sphinx.ext.autosummary',
'sphinx.ext.intersphinx',
'sphinx.ext.todo',
'sphinx.ext.viewcode',
'sphinx.ext.napoleon',
Expand All @@ -37,10 +38,21 @@
todo_include_todos = True
suppress_warnings = ["ref.python"]
autosummary_generate = True
autosummary_imported_members = True
autosummary_imported_members = False
autodoc_default_options = {
'members': True,
'show-inheritance': True,
'private-members': (
'_downstream_pathlength,' # from axon
'_similar_section,' # from axon
'_tree_distance,' # from axon
'_get_sholl_proba,' # from main
'_sanitize_one,' # from sanitize
'_fix_downstream,' # from zero_diameter_fixer
'_fix_in_between,' # from zero_diameter_fixer
'_fix_upstream,' # from zero_diameter_fixer
'_get_cut_leaves,' # from cut_plane.cut_leaves
)
}

# Add any paths that contain templates here, relative to this directory.
Expand All @@ -65,6 +77,14 @@
"repo_name": "BlueBrain/NeuroR"
}

intersphinx_mapping = {
"morphio": ("https://morphio.readthedocs.io/en/latest", None),
"neurom": ("https://neurom.readthedocs.io/en/stable", None),
"numpy": ("https://numpy.org/doc/stable/", None),
"pandas": ("https://pandas.pydata.org/docs", None),
"python": ("https://docs.python.org/3", None),
}

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
Expand Down
88 changes: 49 additions & 39 deletions neuror/axon.py
Expand Up @@ -14,19 +14,27 @@


def _tree_distance(sec1, sec2):
'''
Returns the number of sections between the 2 sections
'''Returns the number of sections between the 2 sections.
Args:
sec1 (~neurom.core.morphology.Section): the first section
sec2 (~neurom.core.morphology.Section): the second section
Reimplementation of:
https://bbpgitlab.epfl.ch/nse/morphologyrepair/BlueRepairSDK/-/blob/main/BlueRepairSDK/src/helper_axon.cpp#L35
Return:
int: The number of sections
raises: if both sections are not part of the same neurite
Raises:
NeuroRError: if both sections are not part of the same neurite.
Note:
I think the implementation of tree distance is true to the original
but I would expect the tree distance of 2 children with the same parent to be 2 and not 1
Because in the current case, (root, child1) and (child1, child2) have the
same tree distance and it should probably not be the case
.. note::
This is a re-implementation of:
https://bbpgitlab.epfl.ch/nse/morphologyrepair/BlueRepairSDK/-/blob/main/BlueRepairSDK/src/helper_axon.cpp#L35
.. note::
I think the implementation of tree distance is ``True`` to the original
but I would expect the tree distance of 2 children with the same parent to be 2 and not 1
Because in the current case, ``(root, child1)`` and ``(child1, child2)`` have the
same tree distance and it should probably not be the case
'''
original_sections = (sec1, sec2)
dist = 0
Expand Down Expand Up @@ -59,11 +67,11 @@ def _tree_distance(sec1, sec2):


def _downstream_pathlength(section):
'''The sum of this section and its descendents's pathlengths
Reimplementation of the C++ function "children_length":
'''The sum of this section and its descendents's pathlengths.
https://bbpgitlab.epfl.ch/nse/morphologyrepair/BlueRepairSDK/-/blob/main/BlueRepairSDK/src/morphstats.cpp#L112
.. note::
This is a re-implementation of the C++ function "children_length":
https://bbpgitlab.epfl.ch/nse/morphologyrepair/BlueRepairSDK/-/blob/main/BlueRepairSDK/src/morphstats.cpp#L112
'''
ret = section_length(section)
for child in section.children:
Expand All @@ -72,12 +80,14 @@ def _downstream_pathlength(section):


def _similar_section(intact_axons, section):
'''Use the "mirror" technique of BlueRepairSDK to find out the similar section
'''Use the "mirror" technique of BlueRepairSDK to find out the similar section.
https://bbpgitlab.epfl.ch/nse/morphologyrepair/BlueRepairSDK/-/blob/main/BlueRepairSDK/src/helper_axon.cpp#L83
.. note::
This is a re-implementation of:
https://bbpgitlab.epfl.ch/nse/morphologyrepair/BlueRepairSDK/-/blob/main/BlueRepairSDK/src/helper_axon.cpp#L83
Note:
I have *absolutely* no clue why sorting by this metric
.. warning::
I have **absolutely** no clue why sorting by this metric
'''
dists = []
for root in intact_axons:
Expand All @@ -91,7 +101,7 @@ def _similar_section(intact_axons, section):


def _sort_intact_sections_by_score(section, similar_section, axon_branches):
'''Returns an array of sections sorted by their score'''
'''Returns an array of sections sorted by their score.'''
reference = _downstream_pathlength(similar_section) - section_length(section)

def score(branch):
Expand All @@ -102,10 +112,7 @@ def score(branch):


def repair(morphology, section, intact_sections, axon_branches, used_axon_branches, y_extent):
'''Axonal repair
Reimplementation of:
https://bbpgitlab.epfl.ch/nse/morphologyrepair/BlueRepairSDK/-/blob/main/BlueRepairSDK/src/repair.cpp#L727
'''Axonal repair.
1) Find the most similar section in INTACT_SECTIONS list to SECTION
2) Sort AXON_BRANCHES according to a similarity score to the section found at step 1
Expand All @@ -115,22 +122,25 @@ def repair(morphology, section, intact_sections, axon_branches, used_axon_branch
5) Mark this section as used and do not re-use it
Args:
morphology (neurom.Neuron): the morphology to repair
section (neurom.core._neuron.Section): the section to repair
intact_sections (List[Section]): a list of all sections from this morphology
that are part of an intact subtree. Note: these section won't be grafted
axon_branches (List[Section]): a list a intact sections coming from donor morphologies
These are the sections that will be appended
..note::
The original code used to have more parameters. In the context of the bbp-morphology-workflow
it seems that some of the parameters were always used with the same value. This
reimplementation assumes the following BlueRepairSDK options:
- --overlap=true
- --incremental=false
- --restrict=true
- --distmethod=mirror'
morphology (~neurom.core.morphology.Morphology): the morphology to repair
section (neurom.core.morphology.Section): the section to repair
intact_sections (List[~neurom.core.morphology.Section]): a list of all sections from this
morphology that are part of an intact subtree. Note: these section won't be grafted.
axon_branches (List[neurom.core.morphology.Section]): a list a intact sections coming from
donor morphologies. These are the sections that will be appended
.. note::
This is a re-implementation of:
https://bbpgitlab.epfl.ch/nse/morphologyrepair/BlueRepairSDK/-/blob/main/BlueRepairSDK/src/repair.cpp#L727
The original code used to have more parameters. In the context of the
bbp-morphology-workflow it seems that some of the parameters were always used with the
same value. This re-implementation assumes the following BlueRepairSDK options:
- ``--overlap=true``
- ``--incremental=false``
- ``--restrict=true``
- ``--distmethod=mirror``
'''

if not intact_sections:
Expand Down
32 changes: 16 additions & 16 deletions neuror/cli.py
Expand Up @@ -24,19 +24,19 @@
@click.option('-v', '--verbose', count=True, default=0,
help='-v for INFO, -vv for DEBUG')
def cli(verbose):
'''The CLI entry point'''
'''The CLI entry point.'''
level = (logging.WARNING, logging.INFO, logging.DEBUG)[min(verbose, 2)]
L.setLevel(level)


@cli.group()
def unravel():
'''CLI utilities related to unravelling'''
'''CLI utilities related to unravelling.'''


@cli.group()
def cut_plane():
'''CLI utilities related to cut-plane repair'''
'''CLI utilities related to cut-plane repair.'''


@cli.group()
Expand All @@ -50,17 +50,17 @@ def sanitize():

@cut_plane.group()
def compute():
'''CLI utilities to detect cut planes'''
'''CLI utilities to detect cut planes.'''


@cut_plane.group()
def repair():
'''CLI utilities to repair cut planes'''
'''CLI utilities to repair cut planes.'''


@cli.group()
def error_annotation():
'''CLI utilities related to error annotations'''
'''CLI utilities related to error annotations.'''


@error_annotation.command(short_help='Annotate errors on a morphology')
Expand Down Expand Up @@ -125,7 +125,7 @@ def folder(input_dir, output_dir, error_summary_file, marker_file):
help=('Path to a CSV whose columns represents the X, Y and Z '
'coordinates of points from which to start the repair'))
def file(input_file, output_file, plot_file, axon_donor, cut_file):
'''Repair dendrites of a cut neuron'''
'''Repair dendrites of a cut neuron.'''
import pandas

from neuror.main import repair # pylint: disable=redefined-outer-name
Expand All @@ -151,7 +151,7 @@ def file(input_file, output_file, plot_file, axon_donor, cut_file):
help=('A dir with the cut points CSV file for each morphology. '
'See also "neuror cut-plane repair file --help".'))
def folder(input_dir, output_dir, plot_dir, axon_donor, cut_file_dir):
'''Repair dendrites of all neurons in a directory'''
'''Repair dendrites of all neurons in a directory.'''
from neuror.full import repair_all
repair_all(input_dir, output_dir, axons=axon_donor, cut_points_dir=cut_file_dir,
plots_dir=plot_dir)
Expand All @@ -165,7 +165,7 @@ def folder(input_dir, output_dir, plot_dir, axon_donor, cut_file_dir):
'and after unravelling'))
@click.option('--window-half-length', default=DEFAULT_WINDOW_HALF_LENGTH)
def file(input_file, output_file, mapping_file, window_half_length):
'''Unravel a cell'''
'''Unravel a cell.'''
from neuror.unravel import unravel # pylint: disable=redefined-outer-name
neuron, mapping = unravel(input_file, window_half_length=window_half_length)
neuron.write(output_file)
Expand Down Expand Up @@ -194,7 +194,7 @@ def folder(input_dir, output_dir, raw_planes_dir, unravelled_planes_dir, window_
@click.argument('folders', nargs=-1)
@click.option('--title', '-t', multiple=True)
def report(folders, title):
'''Generate a PDF with plots of pre and post repair neurons'''
'''Generate a PDF with plots of pre and post repair neurons.'''
from neuror.view import view_all
if not folders:
print('Need to pass at least one folder')
Expand All @@ -211,7 +211,7 @@ def report(folders, title):
@click.argument('input_file')
@click.argument('output_file')
def zero_diameters(input_file, output_file):
'''Output a morphology where the zero diameters have been removed'''
'''Output a morphology where the zero diameters have been removed.'''
from neuror.zero_diameter_fixer import fix_zero_diameters
neuron = Morphology(input_file)
fix_zero_diameters(neuron)
Expand Down Expand Up @@ -241,11 +241,11 @@ def folder(input_folder, output_folder, nprocesses):

@cut_plane.group()
def compute():
'''CLI utilities to compute cut planes'''
'''CLI utilities to compute cut planes.'''


def _check_results(result):
'''Check the result status'''
'''Check the result status.'''
if not result:
L.error('Empty results')
return -1
Expand All @@ -267,7 +267,7 @@ def hint(filename):
Example::
cut-plane compute hint ./tests/data/Neuron_slice.h5
neuror cut-plane compute hint ./tests/data/Neuron_slice.h5
"""
from neuror.cut_plane.viewer import app, set_neuron
set_neuron(filename)
Expand Down Expand Up @@ -352,7 +352,7 @@ def file(filename, output, width, display, plane, position):
Example::
cut-plane compute file -d tests/data/Neuron_slice.h5 -o my-plane.json -w 10
neuror cut-plane compute file -d tests/data/Neuron_slice.h5 -o my-plane.json -w 10
'''
_export_cut_plane(filename, output, width, display, plane or ('x', 'y', 'z'), position)

Expand Down Expand Up @@ -391,7 +391,7 @@ def join(out_filename, plane_paths):
Example::
cut-plane join result.json plane1.json plane2.json plane3.json
neuror cut-plane join result.json plane1.json plane2.json plane3.json
'''
data = []
for plane in plane_paths:
Expand Down
19 changes: 11 additions & 8 deletions neuror/cut_plane/cut_leaves.py
@@ -1,5 +1,8 @@
"""Detect cut leaves with new algo."""
from itertools import product
from typing import List

import morphio
import numpy as np
from neurom.core.dataformat import COLS
from neuror.cut_plane.planes import HalfSpace
Expand All @@ -15,8 +18,8 @@ def _get_cut_leaves(half_space, morphology, bin_width, percentile_threshold):
Args:
half_space (planes.HalfSpace): half space to search cut points
morphology (morphio.Morphology): morphology
bin_width: the bin width
percentile_threshold: the minimum percentile of leaves counts in bins
bin_width (float): the bin width
percentile_threshold (float): the minimum percentile of leaves counts in bins
Returns:
leaves: ndarray of dim (n, 3) with cut leaves coordinates
Expand Down Expand Up @@ -46,11 +49,11 @@ def _get_cut_leaves(half_space, morphology, bin_width, percentile_threshold):


def find_cut_leaves(
morph,
bin_width=3,
percentile_threshold=70.0,
searched_axes=("Z",),
searched_half_spaces=(-1, 1),
morph: morphio.Morphology,
bin_width: float = 3,
percentile_threshold: float = 70.0,
searched_axes: List[str] = ("Z",),
searched_half_spaces: List[float] = (-1, 1),
):
"""Find all cut leaves for cuts with strong signal for real cut.
Expand All @@ -66,7 +69,7 @@ def find_cut_leaves(
Note that all cuts can be valid, thus cut leaves can be on both sides.
Args:
morph (morphio.Morphology): morphology
morph: morphology
bin_width: the bin width
percentile_threshold: the minimum percentile of leaves counts in bins
searched_axes: x, y or z. Specify the half space for which to search the cut leaves
Expand Down

0 comments on commit 70f9e42

Please sign in to comment.