Skip to content

Commit

Permalink
Merge pull request #484 from BlueBrain/numpy-scaler
Browse files Browse the repository at this point in the history
New scaler: NrnSegmentSomaDistanceStepScaler
  • Loading branch information
AurelienJaquier authored Jan 26, 2024
2 parents f56a38f + 21ebe16 commit e05921d
Show file tree
Hide file tree
Showing 9 changed files with 119 additions and 8 deletions.
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
respectively. It can also contain step_begin and step_end.
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

0 comments on commit e05921d

Please sign in to comment.