Skip to content

Commit

Permalink
Dotprops.to_skeleton: carry over soma
Browse files Browse the repository at this point in the history
  • Loading branch information
schlegelp committed Nov 16, 2020
1 parent 0afb088 commit 8ebca51
Showing 1 changed file with 40 additions and 5 deletions.
45 changes: 40 additions & 5 deletions navis/core/neurons.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,20 @@ def wrapper(*args, **kwargs):
return wrapper


def requires_nodes(func):
"""Return ``None`` if neuron has no nodes."""
@functools.wraps(func)
def wrapper(*args, **kwargs):
self = args[0]
# Return 0
if isinstance(self.nodes, str) and self.nodes == 'NA':
return 'NA'
if not isinstance(self.nodes, pd.DataFrame):
return None
return func(*args, **kwargs)
return wrapper


def Neuron(x: Union[nx.DiGraph, str, pd.DataFrame, 'TreeNeuron', 'MeshNeuron'],
**metadata):
"""Constructor for Neuron objects. Depending on the input, either a
Expand Down Expand Up @@ -134,15 +148,24 @@ def __getattr__(self, key):
data = getattr(self, key)
if isinstance(data, pd.DataFrame) and not data.empty:
return True
# This is necessary because np.any does not like strings
elif isinstance(data, str):
if data == 'NA' or not data:
return False
return True
elif np.any(data):
return True
return False
elif key.startswith('n_'):
key = key[key.index('_') + 1:]
if hasattr(self, key):
data = getattr(self, key, None)
if hasattr(data, '__len__'):
if isinstance(data, pd.DataFrame):
return data.shape[0]
elif utils.is_iterable(data):
return len(data)
elif isinstance(data, str) and data == 'NA':
return 'NA'
return None

raise AttributeError(f'Attribute "{key}" not found')
Expand Down Expand Up @@ -992,6 +1015,7 @@ def __getstate__(self):
return state

@property
@requires_nodes
def edges(self) -> np.ndarray:
"""Edges between nodes.
Expand Down Expand Up @@ -1075,19 +1099,24 @@ def core_md5(self) -> str:
if self.has_nodes:
data = np.ascontiguousarray(self.nodes[['node_id', 'parent_id',
'x', 'y', 'z']].values)
if xxhash:
return xxhash.xxh128(data).hexdigest()
return hashlib.md5(data).hexdigest()

@property
@requires_nodes
def leafs(self) -> pd.DataFrame:
"""Leaf node table."""
return self.nodes[self.nodes['type'] == 'end']

@property
@requires_nodes
def ends(self):
"""End node table (same as leafs)."""
return self.leafs

@property
@requires_nodes
def branch_points(self):
"""Branch node table."""
return self.nodes[self.nodes['type'] == 'branch']
Expand Down Expand Up @@ -1145,7 +1174,7 @@ def is_tree(self) -> bool:

@property
def subtrees(self) -> List[List[int]]:
"""List of subtrees (sorted by size) as sets of node IDs."""
"""List of subtrees. Sorted by size as sets of node IDs."""
return sorted(graph._connected_components(self),
key=lambda x: -len(x))

Expand Down Expand Up @@ -1181,6 +1210,7 @@ def _set_connectors(self, v):
restrict=False)

@property
@requires_nodes
def cycles(self) -> Optional[List[int]]:
"""Cycles in neuron if any.
Expand Down Expand Up @@ -1265,6 +1295,7 @@ def soma(self, value: Union[Callable, int, None]) -> None:
raise ValueError('Soma must be function, None or a valid node ID.')

@property
@requires_nodes
def root(self) -> Sequence:
"""Root node(s)."""
roots = self.nodes[self.nodes.parent_id < 0].node_id.values
Expand All @@ -1281,13 +1312,17 @@ def type(self) -> str:
return 'navis.TreeNeuron'

@property
def n_branches(self) -> int:
@requires_nodes
def n_branches(self) -> Optional[int]:
"""Number of branch points."""
return self.nodes[self.nodes.type == 'branch'].shape[0]

@property
def n_leafs(self) -> int:
@requires_nodes
def n_leafs(self) -> Optional[int]:
"""Number of leafs."""
if not not isinstance(self.nodes, pd.DataFrame):
return None
return self.nodes[self.nodes.type == 'end'].shape[0]

@temp_property
Expand Down Expand Up @@ -2175,6 +2210,6 @@ def to_skeleton(self, scale_vec: float = 1) -> TreeNeuron:
# Add some other relevant attributes directly
if self.has_connectors:
tn._connectors = self._connectors
tn._soma = tn._soma
tn._soma = self._soma

return tn

0 comments on commit 8ebca51

Please sign in to comment.