From 63cd77ab831994961290e5dfba624c77171dff8d Mon Sep 17 00:00:00 2001 From: Chris Barnes Date: Thu, 6 Jul 2023 14:02:34 +0100 Subject: [PATCH 1/2] IntEnum for treenode-connector relationships --- docs/source/whats_new.rst | 3 +++ navis/core/__init__.py | 5 +++-- navis/core/base.py | 28 ++++++++++++++++++++++++++-- 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/docs/source/whats_new.rst b/docs/source/whats_new.rst index 074326f6..4b389039 100644 --- a/docs/source/whats_new.rst +++ b/docs/source/whats_new.rst @@ -25,6 +25,9 @@ repository. for format specs and benchmarks) - new :func:`navis.read_nml` function to read single NML file (complements existing :func:`navis.read_nmx` files which are collections of NMLs) + - :class:`navis.NodeConnectorRelation` is an :class:`enum.IntEnum` + encoding relationships between (tree)nodes and connector nodes, + used in neurons' connector tables. - Improvements: - made adding recordings to ``CompartmentModel`` faster - improved logic for splitting NBLAST across cores diff --git a/navis/core/__init__.py b/navis/core/__init__.py index 39b4342e..bf7bfb2a 100644 --- a/navis/core/__init__.py +++ b/navis/core/__init__.py @@ -12,7 +12,7 @@ # GNU General Public License for more details. from .volumes import Volume -from .base import Neuron, BaseNeuron +from .base import Neuron, BaseNeuron, NodeConnectorRelation from .skeleton import TreeNeuron from .mesh import MeshNeuron from .dotprop import Dotprops @@ -25,4 +25,5 @@ NeuronObject = Union[NeuronList, TreeNeuron, BaseNeuron, MeshNeuron] __all__ = ['Volume', 'Neuron', 'BaseNeuron', 'TreeNeuron', 'MeshNeuron', - 'Dotprops', 'VoxelNeuron', 'NeuronList', 'make_dotprops'] + 'Dotprops', 'VoxelNeuron', 'NeuronList', 'make_dotprops', + 'NodeConnectorRelation'] diff --git a/navis/core/base.py b/navis/core/base.py index ca036448..83a0290c 100644 --- a/navis/core/base.py +++ b/navis/core/base.py @@ -12,6 +12,7 @@ # GNU General Public License for more details. import copy +from enum import IntEnum import hashlib import numbers import pint @@ -45,6 +46,27 @@ pint.Quantity([]) +class NodeConnectorRelation(IntEnum): + """An integer describing a (tree)node-connector relationship. + + i.e. "the (tree)node is the connector node" + + Based on the `CATMAID link types`_. + A node PRESYNAPTIC_TO a connector is an output site. + A node POSTSYNAPTIC_TO a connector is an input site. + + .. _`CATMAID link types`: https://github.com/catmaid/CATMAID/blob/2964e04e6e9772aff5d305e72c1b878030fe0e25/django/applications/catmaid/control/link.py#L16 + """ + PRESYNAPTIC_TO = 0 + POSTSYNAPTIC_TO = 1 + ABUTTING = 2 + GAPJUNCTION_WITH = 3 + TIGHTJUNCTION_WITH = 4 + DESMOSOME_WITH = 5 + ATTACHMENT_TO = 6 + CLOSE_TO = 7 + + def Neuron(x: Union[nx.DiGraph, str, pd.DataFrame, 'TreeNeuron', 'MeshNeuron'], **metadata): """Constructor for Neuron objects. Depending on the input, either a @@ -421,7 +443,8 @@ def presynapses(self): raise ValueError('No connector table found.') # Make an educated guess what presynapses are types = self.connectors['type'].unique() - pre = [t for t in types if 'pre' in str(t) or t in [0, "0"]] + pre_int = NodeConnectorRelation.PRESYNAPTIC_TO.value + pre = [t for t in types if 'pre' in str(t) or t in [pre_int, str(pre_int)]] if len(pre) == 0: logger.debug(f'Unable to find presynapses in types: {types}') @@ -442,7 +465,8 @@ def postsynapses(self): raise ValueError('No connector table found.') # Make an educated guess what presynapses are types = self.connectors['type'].unique() - post = [t for t in types if 'post' in str(t) or t in [1, "1"]] + post_int = NodeConnectorRelation.POSTSYNAPTIC_TO.value + post = [t for t in types if 'post' in str(t) or t in [post_int, str(post_int)]] if len(post) == 0: logger.debug(f'Unable to find postsynapses in types: {types}') From 0bb6354120e7a7a0a01f256fa65f889e5922b2c0 Mon Sep 17 00:00:00 2001 From: Chris Barnes Date: Fri, 28 Jul 2023 12:49:31 +0100 Subject: [PATCH 2/2] Add super-duper explicit methods to NodeConnectorRelation --- navis/core/base.py | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/navis/core/base.py b/navis/core/base.py index 83a0290c..8107d3c1 100644 --- a/navis/core/base.py +++ b/navis/core/base.py @@ -51,7 +51,7 @@ class NodeConnectorRelation(IntEnum): i.e. "the (tree)node is the connector node" - Based on the `CATMAID link types`_. + Inspired by the `CATMAID link types`_. A node PRESYNAPTIC_TO a connector is an output site. A node POSTSYNAPTIC_TO a connector is an input site. @@ -59,12 +59,28 @@ class NodeConnectorRelation(IntEnum): """ PRESYNAPTIC_TO = 0 POSTSYNAPTIC_TO = 1 - ABUTTING = 2 - GAPJUNCTION_WITH = 3 - TIGHTJUNCTION_WITH = 4 - DESMOSOME_WITH = 5 - ATTACHMENT_TO = 6 - CLOSE_TO = 7 + # ABUTTING = 2 + # GAPJUNCTION_WITH = 3 + # TIGHTJUNCTION_WITH = 4 + # DESMOSOME_WITH = 5 + # ATTACHMENT_TO = 6 + # CLOSE_TO = 7 + + def is_output_node(self) -> bool: + """Whether the node is sending output via the connector""" + return self == NodeConnectorRelation.PRESYNAPTIC_TO + + def is_input_node(self) -> bool: + """Whether the node is receiving input via the connector""" + return self == NodeConnectorRelation.POSTSYNAPTIC_TO + + def is_output_connector(self) -> bool: + """Whether the connector is sending output to the node""" + return self.is_input_node() + + def is_input_connector(self) -> bool: + """Whether the connector is receiving input from the node""" + return self.is_output_node() def Neuron(x: Union[nx.DiGraph, str, pd.DataFrame, 'TreeNeuron', 'MeshNeuron'],