-
Notifications
You must be signed in to change notification settings - Fork 1
/
front.py
164 lines (140 loc) · 6.24 KB
/
front.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
####################################################################################
#
# NeuroMaC: Neuronal Morphologies & Circuits
# Copyright (C) 2013-2017 Okinawa Institute of Science and Technology Graduate
# University, Japan.
#
# See the file AUTHORS for details.
# This file is part of NeuroMaC.
#
# NeuroMaC is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 3,
# as published by the Free Software Foundation.
#
# NeuroMaC is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#################################################################################
import numpy as np
import time # only for testing
verbose = 0
class Front(object) :
"""
Key component of NeuroMac. A Front is a phenomenological \
growth cone with a dual character:
- A Front is a point in space with a radius. When connected \
to another Front, a frustrum (or cylinder) is created.
- A Front is a phenomenological growth cone that contains a \
set of growth rules.
Each Front has its own set of rules expressed in a Python file \
that is listed in the algo_name variable. Initially, a \
neuronal structure consists of one Front but later, when a structure \
develops by simultaneous expanding of multiple fronts, each front \
can contain different growth-rules.
.. warning:: This code is not to be changed and is directly called \
by NeuroMaC
"""
def __init__(self,entity_name,algo_name,xyz,radius,\
path_length,order) :
"""
Constructor
Parameters
----------
entity_name : string
algo_name : string
File name containing the growth rules must be named :code:`<algo_name>.py`. \
It's this name that is also specified in the configuration file.
xyz : np.array
3D vector
radius : float
"""
# The name given to an entity ~ a neuron
# This name is to be used to query the substrate
self.entity_name = entity_name
# Growth-rules to use
self.algo_name = algo_name
# 3D location
self.xyz = xyz
# Radius of the front
# Consecutive fronts form a frustrum or cylinder
self.radius = radius
# *Not directly set*. Attrribute set by :py:func:`growth_procs.prepare_next_front`
self.path_length= path_length
# *Not directly set*. Attrribute set by :py:func:`growth_procs.prepare_next_front`
self.order = order
# SWC-type as defined in Cannon et al 1998
self.swc_type = 7 # SWC-type field (custom value)
self.soma_pos =None
self.parent = None
def __str__(self):
return "Front " + self.entity_name +": " + str(self.xyz)
def __eq__(self,other):
if other is None: return False
if not self.entity_name == other.entity_name: return False
if not self.algo_name == other.algo_name: return False
if not np.allclose(self.xyz,other.xyz): return False
if not self.radius == other.radius: return False
if not self.path_length == other.path_length: return False
if not self.order == other.order: return False
if not self.swc_type == other.swc_type: return False
if other.soma_pos is None:
if not self.soma_pos is None:
return False
else:
#print ("self.soma_pos=", self.soma_pos, ", other.soma_pos=",other.soma_pos)
if not np.allclose(self.soma_pos,other.soma_pos): return False
if not self.parent == other.parent: return False
# otherwise, these objects are the same!
return True
def __ne__(self,other):
return not self == other
# quick and dirty way to create a unique hash, needed to work with sets
def __key(self):
# WARNING!!! tuple(self.xyz) potentially not correct with rounding errors...
return (self.entity_name, self.algo_name, tuple(self.xyz),\
self.radius,self.path_length,self.order,\
self.swc_type)
def __hash__(self):
return hash(self.__key())
def extend_front(self,seed,constellation,virtual_substrate={}) :
"""
Main function. Outsources the execution to the actual growth-rules \
specified in the configuration file (:code:`cell_type_x` > \
:code:`algorithm`).
See :ref:`implement-rules`
.. note:: This function is not to be modified and is only used \
by framework code (Subvolume.py)
Parameters
----------
seed : int
constellation : dict of list of np.array
virtual_substrate : dict of list
Returns
-------
front : :class:`Front`
List of fronts that are the "extension" of the current front. \
By convention, an empty list of None represents a terminating \
front. A list with one or two entries represents an elongating =\
or a branching front, respectively. One exception can be the \
soma from which multiple new fronts can sprout.
"""
# process the virtual substrate information and set variable in "self"
for key in virtual_substrate.keys():
# setattr(x, attr, 'magic')
for x in virtual_substrate[key].keys():
rectangle = virtual_substrate[key][x]
b0 = np.array(rectangle[0])
b1 = np.array(rectangle[1])
if np.all(self.xyz>b0) and np.all(self.xyz<b1): # works for rectangle only...
setattr(self,key,x)
if verbose:
print (">>>> FOUND: ",key," = ",x)
# outsource the real call to extend a front
globals()[self.algo_name] = __import__(self.algo_name)
ret = globals()[self.algo_name].extend_front(self,seed,constellation)
return ret