Skip to content

Commit

Permalink
split function 'get_morph_and_decor()' into special cases for 1,2,3 s…
Browse files Browse the repository at this point in the history
…egments
  • Loading branch information
jlubo committed Oct 14, 2023
1 parent da87dea commit e72bace
Showing 1 changed file with 178 additions and 132 deletions.
310 changes: 178 additions & 132 deletions python/test/unit/test_diffusion.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,130 +95,166 @@ def __init__(self, args):
self.dt = 0.01 # duration of one timestep in ms
self.dev = 0.01 # accepted relative deviation for `assertAlmostEqual`

# get_morph_and_decor
# Method that sets up and returns a morphology and decoration for given parameters
# - num_segs: number of segments (1, 2, or 3; in the case of 1 or 2, there'll be one branch, in the case of 3, there'll be three branches)
# get_morph_and_decor_1_seg
# Method that sets up and returns a morphology and decoration for one segment with the given parameters
# (one segment => there'll be one branch)
# - num_cvs_per_seg: number of CVs per segment
# - l_1: axial length of the first segment in µm
# - l_2: axial length of the second segment in µm
# - l_3: axial length of the third segment in µm
# - length_1: axial length of the first segment in µm
# - radius_1: radius of the first segment in µm
def get_morph_and_decor_1_seg(self, num_cvs_per_seg, length_1, radius_1):
# ---------------------------------------------------------------------------------------
# set up the morphology
tree = A.segment_tree()
_ = tree.append(
A.mnpos,
A.mpoint(-length_1, 0, 0, radius_1),
A.mpoint(0, 0, 0, radius_1),
tag=0,
)
labels = A.label_dict(
{
"soma-region": "(tag 0)",
"soma-start": '(on-components 0.0 (region "soma-region"))',
"soma-center": '(on-components 0.5 (region "soma-region"))',
"soma-end": '(on-components 1.0 (region "soma-region"))',
}
)
morph = A.morphology(tree)

# ---------------------------------------------------------------------------------------
# decorate the morphology with mechanisms
dec = A.decor()
dec.discretization(
A.cv_policy(f"(fixed-per-branch {num_cvs_per_seg})")
) # use 'fixed-per-branch' policy to obtain exact number of CVs; there's one branch here
dec.place('"soma-end"', A.synapse("synapse_with_diffusion"), "syn_exc_A")
dec.place('"soma-end"', A.synapse("synapse_with_diffusion"), "syn_exc_B")
dec.place('"soma-end"', A.synapse("synapse_with_diffusion"), "syn_inh")
dec.paint("(all)", A.density("neuron_with_diffusion"))

return morph, dec, labels

# get_morph_and_decor_2_seg
# Method that sets up and returns a morphology and decoration for two segments with the given parameters
# (two segments => there'll be one branch)
# - num_cvs_per_seg: number of CVs per segment
# - length_1: axial length of the first segment in µm
# - length_2: axial length of the second segment in µm
# - radius_1: radius of the first segment in µm
# - radius_2: radius of the second segment in µm
# - radius_3: radius of the third segment in µm
def get_morph_and_decor(
self, num_segs, num_cvs_per_seg, l_1, l_2, l_3, radius_1, radius_2, radius_3
def get_morph_and_decor_2_seg(
self, num_cvs_per_seg, length_1, length_2, radius_1, radius_2
):
# ---------------------------------------------------------------------------------------
# set up the morphology
tree = A.segment_tree()
if num_segs == 1:
_ = tree.append(
A.mnpos,
A.mpoint(-l_1, 0, 0, radius_1),
A.mpoint(0, 0, 0, radius_1),
tag=0,
)
s = tree.append(
A.mnpos,
A.mpoint(-length_1, 0, 0, radius_1),
A.mpoint(0, 0, 0, radius_1),
tag=0,
)
_ = tree.append(
s,
A.mpoint(0, 0, 0, radius_2),
A.mpoint(+length_2, 0, 0, radius_2),
tag=1,
)
labels = A.label_dict(
{
"soma-region": "(tag 0)",
"dendriteA-region": "(tag 1)",
"soma-start": '(on-components 0.0 (region "soma-region"))',
"soma-center": '(on-components 0.5 (region "soma-region"))',
"soma-end": '(on-components 1.0 (region "soma-region"))',
"dendriteA-center": '(on-components 0.5 (region "dendriteA-region"))',
}
)
morph = A.morphology(tree)

labels = A.label_dict(
{
"soma-region": "(tag 0)",
"soma-start": '(on-components 0.0 (region "soma-region"))',
"soma-center": '(on-components 0.5 (region "soma-region"))',
"soma-end": '(on-components 1.0 (region "soma-region"))',
}
)
elif num_segs == 2:
s = tree.append(
A.mnpos,
A.mpoint(-l_1, 0, 0, radius_1),
A.mpoint(0, 0, 0, radius_1),
tag=0,
)
_ = tree.append(
s,
A.mpoint(0, 0, 0, radius_2),
A.mpoint(+l_2, 0, 0, radius_2),
tag=1,
)
# ---------------------------------------------------------------------------------------
# decorate the morphology with mechanisms
dec = A.decor()
dec.discretization(
A.cv_policy(f"(fixed-per-branch {2*num_cvs_per_seg})")
) # use 'fixed-per-branch' policy to obtain exact number of CVs; there's one branch here
dec.place(
'"dendriteA-center"', A.synapse("synapse_with_diffusion"), "syn_exc_A"
)
dec.place('"soma-end"', A.synapse("synapse_with_diffusion"), "syn_exc_B")
dec.place('"soma-end"', A.synapse("synapse_with_diffusion"), "syn_inh")
dec.paint("(all)", A.density("neuron_with_diffusion"))

labels = A.label_dict(
{
"soma-region": "(tag 0)",
"dendriteA-region": "(tag 1)",
"soma-start": '(on-components 0.0 (region "soma-region"))',
"soma-center": '(on-components 0.5 (region "soma-region"))',
"soma-end": '(on-components 1.0 (region "soma-region"))',
"dendriteA-center": '(on-components 0.5 (region "dendriteA-region"))',
}
)
elif num_segs == 3:
s = tree.append(
A.mnpos,
A.mpoint(-l_1, 0, 0, radius_1),
A.mpoint(0, 0, 0, radius_1),
tag=0,
)
_ = tree.append(
s,
A.mpoint(0, 0, 0, radius_2),
A.mpoint(+l_2, 0, 0, radius_2),
tag=1,
)
_ = tree.append(
s,
A.mpoint(0, 0, 0, radius_3),
A.mpoint(+l_3, 0, 0, radius_3),
tag=2,
)
return morph, dec, labels

labels = A.label_dict(
{
"soma-region": "(tag 0)",
"dendriteA-region": "(tag 1)",
"dendriteB-region": "(tag 2)",
"soma-start": '(on-components 0.0 (region "soma-region"))',
"soma-center": '(on-components 0.5 (region "soma-region"))',
"soma-end": '(on-components 1.0 (region "soma-region"))',
"dendriteA-center": '(on-components 0.5 (region "dendriteA-region"))',
"dendriteB-center": '(on-components 0.5 (region "dendriteB-region"))',
}
)
else:
raise ValueError(
f"Specified number of segments ({num_segs}) not supported."
)
# get_morph_and_decor_3_seg
# Method that sets up and returns a morphology and decoration for three segments with the given parameters
# (three segments => there'll be three branches)
# - num_cvs_per_seg: number of CVs per segment
# - length_1: axial length of the first segment in µm
# - length_2: axial length of the second segment in µm
# - length_3: axial length of the third segment in µm
# - radius_1: radius of the first segment in µm
# - radius_2: radius of the second segment in µm
# - radius_3: radius of the third segment in µm
def get_morph_and_decor_3_seg(
self,
num_cvs_per_seg,
length_1,
length_2,
length_3,
radius_1,
radius_2,
radius_3,
):
# ---------------------------------------------------------------------------------------
# set up the morphology
tree = A.segment_tree()
s = tree.append(
A.mnpos,
A.mpoint(-length_1, 0, 0, radius_1),
A.mpoint(0, 0, 0, radius_1),
tag=0,
)
_ = tree.append(
s,
A.mpoint(0, 0, 0, radius_2),
A.mpoint(+length_2, 0, 0, radius_2),
tag=1,
)
_ = tree.append(
s,
A.mpoint(0, 0, 0, radius_3),
A.mpoint(+length_3, 0, 0, radius_3),
tag=2,
)
labels = A.label_dict(
{
"soma-region": "(tag 0)",
"dendriteA-region": "(tag 1)",
"dendriteB-region": "(tag 2)",
"soma-start": '(on-components 0.0 (region "soma-region"))',
"soma-center": '(on-components 0.5 (region "soma-region"))',
"soma-end": '(on-components 1.0 (region "soma-region"))',
"dendriteA-center": '(on-components 0.5 (region "dendriteA-region"))',
"dendriteB-center": '(on-components 0.5 (region "dendriteB-region"))',
}
)
morph = A.morphology(tree)

# ---------------------------------------------------------------------------------------
# decorate the morphology with mechanisms
dec = A.decor()
if num_segs == 1:
dec.discretization(
A.cv_policy(f"(fixed-per-branch {num_segs*num_cvs_per_seg})")
) # there is only branch here, use 'fixed-per-branch' policy to obtain exact number of CVs
dec.place('"soma-end"', A.synapse("synapse_with_diffusion"), "syn_exc_A")
dec.place('"soma-end"', A.synapse("synapse_with_diffusion"), "syn_exc_B")
dec.place('"soma-end"', A.synapse("synapse_with_diffusion"), "syn_inh")
elif num_segs == 2:
dec.discretization(
A.cv_policy(f"(fixed-per-branch {num_segs*num_cvs_per_seg})")
) # there is only branch here, use 'fixed-per-branch' policy to obtain exact number of CVs
dec.place(
'"dendriteA-center"', A.synapse("synapse_with_diffusion"), "syn_exc_A"
)
dec.place('"soma-end"', A.synapse("synapse_with_diffusion"), "syn_exc_B")
dec.place('"soma-end"', A.synapse("synapse_with_diffusion"), "syn_inh")
elif num_segs == 3:
dec.discretization(
A.cv_policy(f"(fixed-per-branch {num_cvs_per_seg})")
) # there are three branches here, use 'fixed-per-branch' policy to obtain exact number of CVs
dec.place(
'"dendriteA-center"', A.synapse("synapse_with_diffusion"), "syn_exc_A"
)
dec.place(
'"dendriteB-center"', A.synapse("synapse_with_diffusion"), "syn_exc_B"
)
dec.place('"soma-end"', A.synapse("synapse_with_diffusion"), "syn_inh")
dec.discretization(
A.cv_policy(f"(fixed-per-branch {num_cvs_per_seg})")
) # use 'fixed-per-branch' policy to obtain exact number of CVs; there are three branches here
dec.place(
'"dendriteA-center"', A.synapse("synapse_with_diffusion"), "syn_exc_A"
)
dec.place(
'"dendriteB-center"', A.synapse("synapse_with_diffusion"), "syn_exc_B"
)
dec.place('"soma-end"', A.synapse("synapse_with_diffusion"), "syn_inh")
dec.paint("(all)", A.density("neuron_with_diffusion"))

return morph, dec, labels
Expand Down Expand Up @@ -248,43 +284,53 @@ def simulate_and_test_diffusion(
r_3=4.0,
):
# ---------------------------------------------------------------------------------------
# set parameters and calculate geometrical measures
# set parameters
inject_remove = [
{"time": 0.1, "synapse": "syn_exc_A", "change": 600},
{"time": 0.5, "synapse": "syn_exc_B", "change": 1200},
{"time": 1.5, "synapse": "syn_inh", "change": -1400},
] # changes in particle amount (in 1e-18 mol)
diffusivity = 1 # diffusivity (in m^2/s)

# ---------------------------------------------------------------------------------------
# get morphology, decoration, and labels, and calculate geometrical measures
if num_segs == 1:
r_2 = l_2 = 0 # set radius and length of second segment to zero
r_3 = l_3 = 0 # set radius and length of third segment to zero
morph, dec, labels = self.get_morph_and_decor_1_seg(
num_cvs_per_seg, l_1, r_1
) # get morphology, decoration, and labels
length_soma_cv = (
l_1 / num_cvs_per_seg
) # consider 'fixed-per-branch' policy for one segment that forms one branch
) # consider 'fixed-per-branch' policy for one segment, which forms one branch
elif num_segs == 2:
r_3 = l_3 = 0 # set radius and length of third segment to zero
morph, dec, labels = self.get_morph_and_decor_2_seg(
num_cvs_per_seg, l_1, l_2, r_1, r_2
) # get morphology, decoration, and labels
length_soma_cv = (l_1 + l_2) / (
2 * num_cvs_per_seg
) # consider 'fixed-per-branch' policy for two segments that still only form one branch
else:
) # consider 'fixed-per-branch' policy for two segments, which only form one branch
elif num_segs == 3:
morph, dec, labels = self.get_morph_and_decor_3_seg(
num_cvs_per_seg, l_1, l_2, l_3, r_1, r_2, r_3
) # get morphology, decoration, and labels
length_soma_cv = (
l_1 / num_cvs_per_seg
) # consider 'fixed-per-branch' policy for three segments which form three branches

volume_tot = np.pi * (
r_1**2 * l_1 + r_2**2 * l_2 + r_3**2 * l_3
) # volume of the whole setup in µm^3
) # consider 'fixed-per-branch' policy for three segments, which form three branches
else:
raise ValueError(
f"Specified number of segments ({num_segs}) not supported."
)
volume_soma_cv = np.pi * (
r_1**2 * length_soma_cv
) # volume of one cylindrical CV of the first segment in µm^3

inject_remove = [
{"time": 0.1, "synapse": "syn_exc_A", "change": 600},
{"time": 0.5, "synapse": "syn_exc_B", "change": 1200},
{"time": 1.5, "synapse": "syn_inh", "change": -1400},
] # changes in particle amount (in 1e-18 mol)
diffusivity = 1 # diffusivity (in m^2/s)
# print(f"Testing l_1={l_1}, l_2={l_2}, l_3={l_3}, r_1={r_1}, r_2={r_2}, r_3={r_3}")
volume_tot = np.pi * (
r_1**2 * l_1 + r_2**2 * l_2 + r_3**2 * l_3
) # volume of the whole setup in µm^3

# ---------------------------------------------------------------------------------------
# get morphology, decoration, and labels, and add the diffusive particle species 's'
morph, dec, labels = self.get_morph_and_decor(
num_segs, num_cvs_per_seg, l_1, l_2, l_3, r_1, r_2, r_3
)
# add the diffusive particle species 's'
dec.set_ion("s", int_con=0.0, diff=diffusivity)

# ---------------------------------------------------------------------------------------
Expand Down Expand Up @@ -392,8 +438,7 @@ def test_diffusion_equal_radii(self, diffusion_catalogue):
diffusion_catalogue, 3, 50, l_1=5, l_2=5, l_3=5, r_1=4, r_2=4, r_3=4
) # 3 segments with radius 4 µm

""" TODO: not succeeding as of Arbor v0.9.0: """

""" TODO: not succeeding as of Arbor v0.9.0:
# test_diffusion_different_length
# Test: simulations with segments of different length but equal radius
# - diffusion_catalogue: catalogue of diffusion mechanisms
Expand All @@ -420,3 +465,4 @@ def test_diffusion_different_radii(self, diffusion_catalogue):
self.simulate_and_test_diffusion(
diffusion_catalogue, 3, 50, l_1=5, l_2=5, l_3=5, r_1=4, r_2=6, r_3=6
) # 3 segments with radius 4 µm and 6 µm
"""

0 comments on commit e72bace

Please sign in to comment.