Skip to content

Commit

Permalink
3.0.0 (#950)
Browse files Browse the repository at this point in the history
New major release. See CHANGELOG.rst for more details on changes.

- rename neuron to morphology
- refactor features
- refactor viewer
- allow pass arguments to neurom stats
  • Loading branch information
asanin-epfl authored Aug 30, 2021
1 parent 76b8c55 commit a2aa4b4
Show file tree
Hide file tree
Showing 106 changed files with 5,124 additions and 5,513 deletions.
45 changes: 45 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,51 @@
Changelog
=========

Version 3.0.0
-------------
- Rename all 'neuron' names to 'morphology' names, including module and package names. Previous
'neuron' names still exist but deprecated. It is recommended to use new names:

- ``neurom.check.neuron_checks`` => ``neurom.check.morphology_checks``, replace `neuron_checks`
with `morphology_checks` in configs for ``neurom check``.
- ``neurom.core.neuron`` => ``neurom.core.morphology``
- ``neurom.core.neuron.Neuron`` => ``neurom.core.morphology.Morphology``
- ``neurom.core.neuron.graft_neuron`` => ``neurom.core.morphology.graft_morphology``
- ``neurom.io.utils.load_neuron`` => ``neurom.io.utils.load_morphology``
- ``neurom.io.utils.load_neurons`` => ``neurom.io.utils.load_morphologies``
- ``neurom.core.Population.neurons`` => ``neurom.core.Population.morphologies``

- Refactor plotting functionality. :ref:`migration-v3.0.0`.
- deprecate ``neurom.view.viewer``
- rename ``neurom.view.view`` to ``neurom.view.matplotlib_impl``
- rename ``neurom.view.plotly`` to ``neurom.view.plotly_impl``
- rename ``neurom.view.common`` to ``neurom.view.matplotlib_utils``
- swap arguments ``ax`` and ``nrn`` of all plot functions in ``neurom.view.matplotlib_impl``,
also ``nrn`` arg is renamed to ``morph``.
- delete ``neurom.view.plotly.draw``. Use instead ``neurom.view.plotly_impl.plot_morph`` and
``neurom.view.plotly_impl.plot_morph3d``.

- Refactor features.
- Drop 'func' suffix of all module names within `features` package:
- ``neurom.features.bifurcationfunc`` => ``neurom.features.bifurcation``
- ``neurom.features.sectionfunc`` => ``neurom.features.section``
- ``neurom.features.neuritefunc`` => ``neurom.features.neurite``
- ``neurom.features.neuronfunc`` => ``neurom.features.morphology``
- Rigid classification of features. ``neurite`` features must accept only a single neurite.
``morphology`` features must accept only a single morphology. ``population`` features must
accept only a collection of neurons or a neuron population.
- Some features were deleted, renamed, added. See :ref:`migration-v3.0.0`.
- Name consistency among private variables.
- Delete deprecated `neurom.features.register_neurite_feature`.

- Refactor morphology statistics, e.g. ``neurom stats`` command.
- New config format. See :ref:`morph-stats-new-config`. The old format is still supported.
The only necessary change is replace 'total' with 'sum', 'neuron' with 'morphology'.
- Keep feature names as is. Don't trim 's' at the end of plurals.

- Delete ``neurom.check.structural_checks``, ``neurom.core.tree`` that were deprecated in v2.
- Delete unused ``neurom.utils.memoize``

Version 2.3.1
-------------
- fix ``features.neuronfunc._neuron_population`` for 'sholl_frequency' feature over a neuron
Expand Down
2 changes: 2 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
include requirements.txt
include requirements_dev.txt
include README.rst
recursive-exclude tests *
recursive-exclude tutorial *
graft neurom/config
20 changes: 11 additions & 9 deletions doc/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,21 @@ API Documentation

neurom.morphmath
neurom.features
neurom.features.neuronfunc
neurom.features.neuritefunc
neurom.features.sectionfunc
neurom.features.bifurcationfunc
neurom.features.population
neurom.features.morphology
neurom.features.neurite
neurom.features.section
neurom.features.bifurcation
neurom.check.morphtree
neurom.check.neuron_checks
neurom.check.morphology_checks
neurom.core.types
neurom.core.neuron
neurom.core.morphology
neurom.core.population
neurom.core.soma
neurom.core.dataformat
neurom.io.utils
neurom.view
neurom.view.common
neurom.view.view
neurom.viewer
neurom.view.dendrogram
neurom.view.matplotlib_utils
neurom.view.matplotlib_impl
neurom.view.plotly_impl
18 changes: 9 additions & 9 deletions doc/source/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,30 +38,30 @@ Examples
Fast analysis with :py:mod:`neurom`
***********************************

Here we load a neuron and obtain some information from it:
Here we load a morphology and obtain some information from it:

.. code-block:: python
>>> import neurom as nm
>>> nrn = nm.load_neuron('some/data/path/morph_file.swc')
>>> ap_seg_len = nm.get('segment_lengths', nrn, neurite_type=nm.APICAL_DENDRITE)
>>> ax_sec_len = nm.get('section_lengths', nrn, neurite_type=nm.AXON)
>>> m = nm.load_morphology('some/data/path/morph_file.swc')
>>> ap_seg_len = nm.get('segment_lengths', m, neurite_type=nm.APICAL_DENDRITE)
>>> ax_sec_len = nm.get('section_lengths', m, neurite_type=nm.AXON)
Morphology visualization with the :py:mod:`neurom.viewer` module
****************************************************************

Here we visualize a neuronal morphology:
Here we visualize a morphology:


.. code-block:: python
>>> # Initialize nrn as above
>>> # Initialize m as above
>>> from neurom import viewer
>>> fig, ax = viewer.draw(nrn)
>>> fig, ax = viewer.draw(m)
>>> fig.show()
>>>
>>> fig, ax = viewer.draw(nrn, mode='3d') # valid modes '2d', '3d', 'dendrogram'
>>> fig, ax = viewer.draw(m, mode='3d') # valid modes '2d', '3d', 'dendrogram'
>>> fig.show()
Advanced iterator-based feature extraction example
Expand All @@ -79,7 +79,7 @@ All of the examples in the previous sections can be implemented
in a similar way to those presented here.


.. literalinclude:: ../../examples/neuron_iteration_analysis.py
.. literalinclude:: ../../examples/iteration_analysis.py
:lines: 30-

Getting Log Information
Expand Down
123 changes: 123 additions & 0 deletions doc/source/features.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
.. Copyright (c) 2015, Ecole Polytechnique Federale de Lausanne, Blue Brain Project
All rights reserved.
This file is part of NeuroM <https://github.com/BlueBrain/NeuroM>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of
its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.. _features:

Features
********
A tool for analysing of morphologies. It allows to extract various information about morphologies.
For example if you need to know the segment lengths of a morphology then you need to call
``segment_lengths`` feature. The complete list of available features is spread among pages
:mod:`neurom.features.neurite`, :mod:`neurom.features.morphology`,
:mod:`neurom.features.population`.

Features are spread among ``neurite``, ``morphology``, ``population`` modules to emphasize their
expected input. Features from ``neurite`` expect a neurite as their input. So calling it with
a morphology input will fail. ``morphology`` expects a morphology only. ``population`` expects a
population only.

This restriction can be bypassed if you call a feature from ``neurite`` via the features
mechanism ``features.get``. However the mechanism does not allow to appply ``population``
features to anything other than a morphology population, and ``morphology`` features can be applied
only to a morphology or a morphology population.

An example for ``neurite``:

.. code-block:: python
from neurom import load_morphology, features
from neurom.features.neurite import max_radial_distance
m = load_morphology('path/to/morphology')
# valid input
max_radial_distance(m.neurites[0])
# invalid input
max_radial_distance(m)
# valid input
features.get('max_radial_distance', m)
The features mechanism assumes that a neurite feature must be summed if it returns a number, and
concatenated if it returns a list. Other types of returns are invalid. For example lets take
a feature ``number_of_segments`` of ``neurite``. It returns a number of segments in a neurite.
Calling it on a morphology will return a sum of ``number_of_segments`` of all the morphology's neurites.
Calling it on a morphology population will return a list of ``number_of_segments`` of each morphology
within the population.


.. code-block:: python
from neurom import load_morphology, features
m = load_morphology('path/to/morphology')
# a single number
features.get('number_of_segments', m.neurites[0])
# a single number that is a sum for all `m.neurites`.
features.get('number_of_segments', m)
pop = load_morphology('path/to/morphology population')
# a list of numbers
features.get('number_of_segments', pop)
if a list is returned then the feature results are concatenated.

.. code-block:: python
from neurom import load_morphology, features
m = load_morphology('path/to/morphology')
# a list of lengths in a neurite
features.get('section_lengths', m.neurites[0])
# a flat list of lengths in a morphology, no separation among neurites
features.get('section_lengths', m)
pop = load_morphology('path/to/morphology population')
# a flat list of lengths in a population, no separation among morphologies
features.get('section_lengths', pop)
In case such implicit behaviour does not work a feature can be rewritten for each input separately.
For example, a feature ``max_radial_distance`` that requires a `max` operation instead of implicit
`sum`. Its definition in ``neurite``:

.. literalinclude:: ../../neurom/features/neurite.py
:pyobject: max_radial_distance

In order to make it work for a morphology, it is redefined in ``morphology``:

.. literalinclude:: ../../neurom/features/morphology.py
:pyobject: max_radial_distance

Another feature that requires redefining is ``sholl_frequency``. This feature applies different
logic for a morphology and a morphology population. That is why it is defined in ``morphology``:

.. literalinclude:: ../../neurom/features/morphology.py
:pyobject: sholl_frequency

and redefined in ``population``

.. literalinclude:: ../../neurom/features/population.py
:pyobject: sholl_frequency
5 changes: 3 additions & 2 deletions doc/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
NeuroM
======

NeuroM is a Python-based toolkit for the analysis and processing of neuron morphologies.
NeuroM is a Python-based toolkit for the analysis and processing of morphologies.

.. toctree::
:hidden:
Expand All @@ -43,12 +43,13 @@ NeuroM is a Python-based toolkit for the analysis and processing of neuron morph
install
validation
tutorial
features
examples
cli
definitions
api
developer
documentation
migration_v2
migration
changelog
license
66 changes: 61 additions & 5 deletions doc/source/migration_v2.rst → doc/source/migration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,67 @@
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.. _migration-v2:

Migration guides
=======================

.. _migration-v3.0.0:

Migration to v3 version
-----------------------

- ``neurom.view.viewer`` is deprecated. To get the same results as before, use the replacement:

.. code-block:: python
import neurom as nm
# instead of: from neurom import viewer
from neurom.view import matplotlib_impl, matplotlib_utils
m = nm.load_morphology('some/data/path/morph_file.asc')
# instead of: viewer.draw(m)
matplotlib_impl.plot_morph(m)
# instead of: viewer.draw(m, mode='3d')
matplotlib_impl.plot_morph3d(m)
# instead of: viewer.draw(m, mode='dendrogram')
matplotlib_impl.plot_dendrogram(m)
# If you used ``output_path`` with any of functions above then the solution is:
fig, ax = matplotlib_utils.get_figure()
matplotlib_impl.plot_dendrogram(m, ax)
matplotlib_utils.plot_style(fig=fig, ax=ax)
matplotlib_utils.save_plot(fig=fig, output_path=output_path)
# for other plots like `plot_morph` it is the same, you just need to call `plot_morph` instead
# of `plot_dendrogram`.
# instead of `plotly.draw`
from neurom import plotly_impl
plotly_impl.plot_morph(m) # for 2d
plotly_impl.plot_morph3d(m) # for 3d
- breaking features changes:
- use `max_radial_distance` instead of `max_radial_distances`
- use `number_of_segments` instead of `n_segments`
- use `number_of_neurites` instead of `n_neurites`
- use `number_of_sections` instead of `n_sections`
- use `number_of_bifurcations` instead of `n_bifurcation_points`
- use `number_of_forking_points` instead of `n_forking_points`
- use `number_of_leaves` instead of `number_of_terminations`, `n_leaves`
- use `soma_radius` instead of `soma_radii`
- use `soma_surface_area` instead of `soma_surface_areas`
- use `soma_volume` instead of `soma_volumes`
- use `total_length_per_neurite` instead of `neurite_lengths`
- use `total_volume_per_neurite` instead of `neurite_volumes`
- use `terminal_path_lengths` instead of `terminal_path_lengths_per_neurite`
- use `bifurcation_partitions` instead of `partition`
- new neurite feature `total_area` that complements `total_area_per_neurite`
- new neurite feature `volume_density` that complements `neurite_volume_density`


Migration to v2 version
=======================
-----------------------
.. _migration-v2:

- ``Neuron`` object now extends ``morphio.Morphology``.
- NeuroM does not remove unifurcations on load. Unifurcation is a section with a single child. Such
Expand All @@ -40,10 +96,10 @@ Migration to v2 version
.. code-block:: python
import neurom as nm
nrn = nm.load_neuron('some/data/path/morph_file.asc')
nrn = nm.load_morphology('some/data/path/morph_file.asc')
nrn.remove_unifurcations()
- Soma is not considered as a section anymore. Soma is skipped when iterating over neuron's
- Soma is not considered as a section anymore. Soma is skipped when iterating over morphology's
sections. It means that section indexing offset needs to be adjusted by
``-(number of soma sections)`` which is usually ``-1``.
- drop ``benchmarks``
Expand Down
8 changes: 4 additions & 4 deletions doc/source/morph_check.rst
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ An example usage
The tests are grouped in two categories:

1. Structural tests. **Dropped in v2 version**.
2. Neuron tests. These are applied to properties of reconstructed neurons and their
2. Morphology tests. These are applied to properties of reconstructed morphologies and their
constituent soma and neurites, and can be thought of as "quality" checks.


Expand All @@ -58,7 +58,7 @@ mentioned above. Here is an example configuration:
.. code-block:: yaml
checks:
neuron_checks:
morphology_checks:
- has_basal_dendrite
- has_axon
- has_all_nonzero_segment_lengths
Expand All @@ -74,8 +74,8 @@ mentioned above. Here is an example configuration:
As can be seen, the configuration file is split into two sections ``checks``, and ``options``.
``checks`` can only have `neuron_checks` sub-item that corresponds to a sub-module
:py:mod:`neuron_checks<neurom.check.neuron_checks>`. Each of its sub-items corresponds to a function
``checks`` can only have `morphology_checks` sub-item that corresponds to a sub-module
:py:mod:`morphology_checks<neurom.check.morphology_checks>`. Each of its sub-items corresponds to a function
in that sub-module.


Expand Down
Loading

0 comments on commit a2aa4b4

Please sign in to comment.