Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New scaler: NrnSegmentSomaDistanceStepScaler #484

Merged
merged 10 commits into from
Jan 26, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions bluepyopt/ephys/create_hoc.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,18 @@ def range_exprs_to_hoc(range_params):
for param in range_params:
value = param.value_scaler.inst_distribution
value = re.sub(r'math\.', '', value)
value = re.sub(r'\&', '&&', value)
value = re.sub('{distance}', FLOAT_FORMAT, value)
value = re.sub('{value}', format_float(param.value), value)
if hasattr(param.value_scaler, "step_begin"):
value = re.sub(
'{step_begin}',
format_float(param.value_scaler.step_begin),
value
)
value = re.sub(
'{step_end}', format_float(param.value_scaler.step_end), value
)
ret.append(Range(param.location, param.name, value))
return ret

Expand Down
59 changes: 56 additions & 3 deletions bluepyopt/ephys/parameterscalers/parameterscalers.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,8 @@ def inst_distribution(self):
# Use this special formatting to bypass missing keys
return string.Formatter().vformat(self.distribution, (), dist_dict)

def eval_dist(self, values, distance):
"""Create the final dist string"""

def scale_dict(self, values, distance):
"""Create scale dictionary"""
scale_dict = {}
if isinstance(values, dict):
for k, v in values.items():
Expand All @@ -172,6 +171,12 @@ def eval_dist(self, values, distance):
scale_dict["value"] = format_float(values)
scale_dict["distance"] = format_float(distance)

return scale_dict

def eval_dist(self, values, distance):
"""Create the final dist string"""
scale_dict = self.scale_dict(values, distance)

return self.inst_distribution.format(**scale_dict)

def scale(self, values, segment, sim=None):
Expand Down Expand Up @@ -261,3 +266,51 @@ def acc_scale_iexpr(self, value, constant_formatter=format_float):
ArbFileMorphology.region_labels['somatic'].ref
)
return generate_acc_scale_iexpr(iexpr, variables, constant_formatter)


class NrnSegmentSomaDistanceStepScaler(NrnSegmentSomaDistanceScaler,
ParameterScaler, DictMixin):

"""Scaler based on distance from soma with a step function"""
SERIALIZED_FIELDS = ('name', 'comment', 'distribution', )

def __init__(
self,
name=None,
distribution=None,
comment='',
dist_param_names=None,
soma_ref_location=0.5,
step_begin=None,
step_end=None):
"""Constructor
Args:
name (str): name of this object
distribution (str): distribution of parameter dependent on distance
from soma. string can contain `distance` and/or `value` as
placeholders for the distance to the soma and parameter value
respectivily. It can also contain step_begin and step_end.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

respectively ;)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, fixed in latest commit

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks! looks good to merge

dist_param_names (list): list of names of parameters that
parametrise the distribution. These names will become
attributes of this object.
The distribution string should contain these names, and they
will be replaced by values of the corresponding attributes
soma_ref_location (float): location along the soma used as origin
from which to compute the distances. Expressed as a fraction
(between 0.0 and 1.0).
step_begin (float): distance at which the step begins
step_end (float): distance at which the step ends
"""

super(NrnSegmentSomaDistanceStepScaler, self).__init__(
name, distribution, comment, dist_param_names,
soma_ref_location=soma_ref_location)
self.step_begin = step_begin
self.step_end = step_end

def scale_dict(self, values, distance):
scale_dict = super().scale_dict(values, distance)
scale_dict["step_begin"] = self.step_begin
scale_dict["step_end"] = self.step_end

return scale_dict
2 changes: 1 addition & 1 deletion bluepyopt/ephys/templates/cell_template.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ proc distribute_distance(){local x localobj sl
this.soma[0] distance(0, 0.5)
sprint(distfunc, "%%s %s(%%f) = %s", mech, distfunc)
forsec sl for(x, 0) {
sprint(stmp, distfunc, secname(), x, distance(x))
sprint(stmp, distfunc, secname(), x, distance(x), distance(x))
execute(stmp)
}
}
Expand Down
32 changes: 32 additions & 0 deletions bluepyopt/tests/test_ephys/test_create_hoc.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
import os

from bluepyopt.ephys.acc import ArbLabel
from bluepyopt.ephys.locations import NrnSomaDistanceCompLocation
from bluepyopt.ephys.parameterscalers import NrnSegmentSomaDistanceScaler
from bluepyopt.ephys.parameterscalers import NrnSegmentSomaDistanceStepScaler

from . import utils
from bluepyopt.ephys import create_acc, create_hoc
Expand Down Expand Up @@ -151,3 +153,33 @@ def test_range_exprs_to_hoc():
assert hoc[0].param_name == 'gkbar_hh'
val_gt = '(-0.8696 + 2.087*exp((%.17g)*0.0031))*0.025000000000000001'
assert hoc[0].value == val_gt


@pytest.mark.unit
def test_range_exprs_to_hoc_step_scaler():
"""ephys.create_hoc: Test range_exprs_to_hoc with step scaler"""
# apical_region = ArbLabel("region", "apic", "(tag 4)")
apical_location = NrnSomaDistanceCompLocation(
name='apic100',
soma_distance=100,
seclist_name='apical',
)
param_scaler = NrnSegmentSomaDistanceStepScaler(
name='soma-distance-step-scaler',
distribution='{value} * (0.1 + 0.9 * int('
'({distance} > {step_begin}) & ('
'{distance} < {step_end})))',
step_begin=300,
step_end=500)

range_expr = create_hoc.RangeExpr(
location=apical_location,
name="gCa_LVAstbar_Ca_LVAst",
value=1,
value_scaler=param_scaler
)

hoc = create_hoc.range_exprs_to_hoc([range_expr])
assert hoc[0].param_name == 'gCa_LVAstbar_Ca_LVAst'
val_gt = '1 * (0.1 + 0.9 * int((%.17g > 300) && (%.17g < 500)))'
assert hoc[0].value == val_gt
16 changes: 16 additions & 0 deletions bluepyopt/tests/test_ephys/test_parameterscalers.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,22 @@ def test_NrnSegmentSectionDistanceScaler_eval_dist_with_dict():
== '0.5 + (1 - (abs(10 - 8) / 4)) * 1')


@pytest.mark.unit
def test_NrnSegmentSomaDistanceStepScaler_eval_dist_with_dict():
"""ephys.parameterscalers: eval_dist of NrnSegmentSomaDistanceStepScaler"""

dist = '{value} * (0.1 + 0.9 * int(' \
'({distance} > {step_begin}) & ({distance} < {step_end})))'

scaler = ephys.parameterscalers.NrnSegmentSomaDistanceStepScaler(
distribution=dist, step_begin=300, step_end=500)

_values = {'value': 1}

assert (scaler.eval_dist(values=_values, distance=10)
== '1 * (0.1 + 0.9 * int((10 > 300) & (10 < 500)))')


@pytest.mark.unit
def test_serialize():
"""ephys.parameterscalers: test serialization"""
Expand Down
2 changes: 1 addition & 1 deletion examples/stochkv/stochkv3cell.hoc
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ proc distribute_distance(){local x localobj sl
this.soma[0] distance(0, 0.5)
sprint(distfunc, "%%s %s(%%f) = %s", mech, distfunc)
forsec sl for(x, 0) {
sprint(stmp, distfunc, secname(), x, distance(x))
sprint(stmp, distfunc, secname(), x, distance(x), distance(x))
execute(stmp)
}
}
Expand Down
2 changes: 1 addition & 1 deletion examples/stochkv/stochkv3cell_det.hoc
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ proc distribute_distance(){local x localobj sl
this.soma[0] distance(0, 0.5)
sprint(distfunc, "%%s %s(%%f) = %s", mech, distfunc)
forsec sl for(x, 0) {
sprint(stmp, distfunc, secname(), x, distance(x))
sprint(stmp, distfunc, secname(), x, distance(x), distance(x))
execute(stmp)
}
}
Expand Down
2 changes: 1 addition & 1 deletion examples/stochkv/stochkvcell.hoc
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ proc distribute_distance(){local x localobj sl
this.soma[0] distance(0, 0.5)
sprint(distfunc, "%%s %s(%%f) = %s", mech, distfunc)
forsec sl for(x, 0) {
sprint(stmp, distfunc, secname(), x, distance(x))
sprint(stmp, distfunc, secname(), x, distance(x), distance(x))
execute(stmp)
}
}
Expand Down
2 changes: 1 addition & 1 deletion examples/stochkv/stochkvcell_det.hoc
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ proc distribute_distance(){local x localobj sl
this.soma[0] distance(0, 0.5)
sprint(distfunc, "%%s %s(%%f) = %s", mech, distfunc)
forsec sl for(x, 0) {
sprint(stmp, distfunc, secname(), x, distance(x))
sprint(stmp, distfunc, secname(), x, distance(x), distance(x))
execute(stmp)
}
}
Expand Down
Loading