Skip to content

Commit

Permalink
Cleaning-up basic functionality. Add path distance and gradient based…
Browse files Browse the repository at this point in the history
… growth.

Change-Id: I4ec1a5ca421e82a8b694203a76ef94f17be3ac90
  • Loading branch information
lidakanari committed Nov 23, 2018
1 parent 11702e3 commit 0ace7a6
Show file tree
Hide file tree
Showing 8 changed files with 526 additions and 95 deletions.
5 changes: 3 additions & 2 deletions tns/extract_input/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def default_keys():
'axon': {}}


def distributions(filepath, neurite_types=None, threshold_sec=2, diameter_model=False):
def distributions(filepath, neurite_types=None, threshold_sec=2, diameter_model=False, feature='radial_distances'):
'''Extracts the input distributions from an input population
defined by a directory of swc or h5 files
threshold_sec: defines the minimum accepted number of terminations
Expand Down Expand Up @@ -45,7 +45,8 @@ def fill_input_distributions(input_distr, neurite_type):
input_distr[neurite_type].update(
from_TMD.persistent_homology_angles(pop_tmd,
threshold=threshold_sec,
neurite_type=neurite_type))
neurite_type=neurite_type,
feature=feature))

for ntype in neurite_types:
fill_input_distributions(input_distributions, ntype)
Expand Down
4 changes: 2 additions & 2 deletions tns/extract_input/from_TMD.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
import numpy as np


def persistent_homology_angles(pop, threshold=2, neurite_type='basals'):
def persistent_homology_angles(pop, threshold=2, neurite_type='basals', feature='radial_distances'):
"""Adds the persistent homology extracted from
a population of apicals to the distr dictionary
Each tree in the population is associated with a persistence barcode (diagram)
and a set of angles that will be used as input for synthesis.
"""
ph_ang = [tmd.methods.get_ph_angles(tr) for tr in getattr(pop, neurite_type)]
ph_ang = [tmd.methods.get_ph_angles(tr, feature=feature) for tr in getattr(pop, neurite_type)]

# Keep only the trees whose number of terminations is above the threshold
# Saves the list of persistence diagrams for the selected neurite_type
Expand Down
10 changes: 10 additions & 0 deletions tns/extract_input/from_diameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
from neurom.core import Tree
from neurom import morphmath

default_model = {'Rall_ratio': 3./2.,
'siblings_ratio': 1./3.}


def section_mean_taper(s):
initial_diam = min(s.points[:,3])

Expand Down Expand Up @@ -123,6 +127,9 @@ def model(neuron):
"term_max_diam": [c for c in chain(*term_max_diam)],
"trunk": max_diam,
"trunk_taper": tr_taper}

values[typee-1].update(default_model)

return values


Expand Down Expand Up @@ -161,4 +168,7 @@ def population_model(neurons):
"term_max_diam": [c for c in chain(*term_max_diam)],
"trunk": max_diam,
"trunk_taper": tr_taper}

values[typee-1].update(default_model)

return values
149 changes: 128 additions & 21 deletions tns/generate/algorithms/tmdgrower.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,53 @@ def __init__(self,
self.angles = None
self.bt_all = None

def curate_bif(self, stop, currentBF, currentTR):
'''Checks if selected bar is smaller than current bar length.
Returns the smallest bifurcation for which the length of the bar
is smaller than current one.
If there are no bif left or if the bif is largest than the current
termination target the np.inf is returned instead.
currentSec.stop_criteria["bif_term"]
'''
current_length = np.abs(stop["term"] - stop["bif"])
target_length = np.abs(currentTR - currentBF)

if not self.bif or target_length==np.inf:
return np.inf
if target_length <= current_length:
return currentBF
for b in self.bif:
target_length = np.abs(currentTR - b)
if target_length <= current_length:
return b
return np.inf

def get_stop_criteria(self, currentSec):
"""Returns stop1 and stop2 that are the commonly
shared stop criteria for all TMDPath algorithms.
stop[bif_term] = {ref: the current path distance
bif: the smallest appropriate bifurcation path length
term: the appropriate termination path length
}
"""
currentBF = self.bif[0] if len(self.bif) > 1 else np.inf

b1 = self.curate_bif(currentSec.stop_criteria["bif_term"], currentBF,
round_num(currentSec.stop_criteria["bif_term"]["term"]))

stop1 = {"bif_term": {"ref": self.start_point[:3],
"bif": b1,
"term": round_num(currentSec.stop_criteria["bif_term"]["term"])}}

b2 = self.curate_bif(currentSec.stop_criteria["bif_term"], currentBF,
round_num(self.bt_all[currentSec.stop_criteria["bif_term"]["bif"]]))

stop2 = {"bif_term": {"ref": self.start_point[:3],
"bif": b2,
"term": round_num(self.bt_all[currentSec.stop_criteria["bif_term"]["bif"]])}}

return (stop1, stop2)

def initialize(self):
"""Generates the data to be used for the initialization
of the first section to be grown. Saves the extracted
Expand Down Expand Up @@ -57,36 +104,45 @@ def bifurcate(self, currentSec):
"""
self.bif.remove(currentSec.stop_criteria["bif_term"]["bif"])
ang = self.angles[currentSec.stop_criteria["bif_term"]["bif"]]
dirs = self.bif_method(currentSec.direction, angles=ang)
dir1, dir2 = self.bif_method(currentSec.get_current_direction(), angles=ang)
start_point = np.array(currentSec.points3D[-1])

stops = [{"bif_term": {"ref": self.start_point[:3],
"bif": self.bif[0] if self.bif else np.inf,
"term": round_num(term)}}
for term in [currentSec.stop_criteria["bif_term"]["term"],
self.bt_all[currentSec.stop_criteria["bif_term"]["bif"]]]]
stop1, stop2 = self.get_stop_criteria(currentSec)

return [{'direction': direction,
'start_point': start_point,
'stop': stop,
'process': currentSec.process} for direction, stop in zip(dirs, stops)]
s1 = {'direction': dir1,
'start_point': start_point,
'stop':stop1,
'process': currentSec.process}

s2 = {'direction': dir2,
'start_point': start_point,
'stop':stop2,
'process': currentSec.process}

return s1, s2

def terminate(self, currentSec):
"""When the growth of a section is terminated the "term"
must be removed from the TMD grower
"""
self.term.remove(currentSec.stop_criteria["bif_term"]["term"])
#print 'B: ', currentSec.stop_criteria["bif_term"]["bif"],
#print ' & removed T: ', currentSec.stop_criteria["bif_term"]["term"]

def extend(self, currentSec):
"""Definition of stop criterion for the growth of the current section.
"""
bif_term = currentSec.stop_criteria["bif_term"]
bif_term["bif"] = round_num(self.bif[0]) if self.bif else np.inf

if bif_term["term"] not in self.term:
bif_term["term"] = round_num(self.term[0]) if self.term else np.inf
if bif_term["bif"] not in self.bif and bif_term["bif"] != np.inf:
currentSec.stop_criteria["bif_term"]["bif"] = self.curate_bif(currentSec.stop_criteria["bif_term"],
self.bif[0] if self.bif else np.inf,
round_num(bif_term["term"]))

if bif_term["term"] not in self.term and bif_term["term"] != np.inf:
currentSec.stop_criteria["bif_term"]["term"] = np.min(self.term) if self.term else np.inf

return currentSec.generate()
return currentSec.next()


class TMDApicalAlgo(TMDAlgo):
Expand Down Expand Up @@ -116,19 +172,70 @@ def bifurcate(self, currentSec):
process2 = 'secondary'

start_point = np.array(currentSec.points3D[-1])
stop1, stop2 = self.get_stop_criteria(currentSec)

stop1 = {"bif_term": {"ref": self.start_point[:3],
"bif": self.bif[0] if self.bif else np.inf,
"term": round_num(currentSec.stop_criteria["bif_term"]["term"])}}
s1 = {'direction': dir1,
'start_point': start_point,
'stop':stop1,
'process':process1}

stop2 = {"bif_term": {"ref": self.start_point[:3],
"bif": self.bif[0] if self.bif else np.inf,
"term": round_num(self.bt_all[currentSec.stop_criteria["bif_term"]["bif"]])}}
s2 = {'direction': dir2,
'start_point': start_point,
'stop':stop2,
'process': process2}

return s1, s2

class TMDGradientAlgo(TMDAlgo):
"""TreeGrower of TMD apical growth"""

def bifurcate(self, currentSec):
"""When the section bifurcates two new sections need to be created.
This method computes from the current state the data required for the
generation of two new sections and returns the corresponding dictionaries.
"""
self.bif.remove(currentSec.stop_criteria["bif_term"]["bif"])
ang = self.angles[currentSec.stop_criteria["bif_term"]["bif"]]

current_rd = np.linalg.norm(np.subtract(currentSec.points3D[-1], self.start_point))

if currentSec.process=='major':
dir1, dir2 = bif_methods['directional'](currentSec.direction, angles=ang)
if current_rd <= self.params['apical_distance']:
process1 = 'major'
process2 = 'secondary'
else:
process1 = 'secondary'
process2 = 'secondary'
else:
dir1, dir2 = self.bif_method(currentSec.get_current_direction(), angles=ang)
process1 = 'secondary'
process2 = 'secondary'

start_point = np.array(currentSec.points3D[-1])

def majorize_process(stop, process, input_dir):
difference = np.abs(stop["bif_term"]["bif"] - stop["bif_term"]["term"])
if difference > self.params['bias_length'] and difference != np.inf:
direction1 = (1.0 - self.params['bias']) * np.array(input_dir)
direction2 = self.params['bias'] * np.array(currentSec.direction)
direct = np.add(direction1, direction2).tolist()
return 'major', direct
else:
return process, input_dir

stop1, stop2 = self.get_stop_criteria(currentSec)

if process1 != 'major':
process1, dir1 = majorize_process(stop1, process1, dir1)
process2, dir2 = majorize_process(stop2, process2, dir2)

start_point = np.array(currentSec.points3D[-1])

s1 = {'direction': dir1,
'start_point': start_point,
'stop':stop1,
'process': process1}
'process':process1}

s2 = {'direction': dir2,
'start_point': start_point,
Expand Down
Loading

0 comments on commit 0ace7a6

Please sign in to comment.