Source code for emodelrunner.factsheets.ion_channel_mechanisms

"""To extract ion channel mechanisms information from static parameter files."""

# Copyright 2020-2022 Blue Brain Project / EPFL

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

#     http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import logging
import re


logger = logging.getLogger(__name__)


[docs] def edit_dist_func(value): """Edit function expression to be latex and plot readable. Args: value (str): the distribution function expressed as a string. ex: "(-0.8696 + 2.087*math.exp((x)*0.0031))*3.1236056887012746e-06" Returns: a tuple containing - latex (str): a latex-compatible version of the distrib. function ex: "(-0.8696 + 2.087*e^{x*0.0031})*3.1236056887012746e-06" - value (str): a plottable version of the distrib. function ex: "(-0.8696 + 2.087exp(x*0.0031))*3.1236056887012746e-06" """ if "math" in value: value = value.replace("math.", "") if "(x)" in value: value = value.replace("(x)", "x") latex = re.sub(r"exp*\(([0-9x*-.]*)\)", "e^{\\1}", value) return latex, value
[docs] def get_channel_and_equations( name, param_config, full_name, exp_fun, decay_fun, release_params ): """Returns the channel and a dictionary containing equation type (uniform or exp) and value. Args: name (str): the name of the ion channel and its parameter. should have the form parameter_channel (ex: "gCa_HVAbar_Ca_HVA2") param_config (dict): parameter dictionary taken from parameter data file. should have a "dist" key if the distribution is exponential. full_name (str): should have the form name.section exp_fun (str): the distribution function expressed as a string. ex: "(-0.8696 + 2.087*math.exp((x)*0.0031))*3.1236056887012746e-06" decay_fun (str): the decay function expressed as a string. release_params (dict): final parameters of the optimised cell. Returns: a tuple containing - channel (str): name of the channel (ex: "Ca_HVA2") - biophys (str): parameter name (ex: "gCa_HVAbar") - equation_dict (dict): contains equation values and equation type (uniform or exp) """ # parameter value (obtained from optimisation) value = release_params[full_name] decay_cst = None if decay_fun: decay_cst = release_params["constant.distribution_decay"] # isolate channel and biophys split_name = name.split("_") if len(split_name) == 4: biophys = "_".join(split_name[0:2]) channel = "_".join(split_name[2:4]) elif len(split_name) == 3: biophys = split_name[0] channel = "_".join(split_name[1:3]) elif len(split_name) == 2: biophys = split_name[0] channel = split_name[1] # type if "dist" in param_config: if param_config["dist"] == "exp": type_ = "exponential" value = exp_fun.format(distance="x", value=value) latex, plot = edit_dist_func(value) elif param_config["dist"] == "decay": type_ = "decay" value = decay_fun.format(distance="x", value=value, constant=decay_cst) latex, plot = edit_dist_func(value) else: logger.warning( "dist is set to %s. Expected 'exp' or 'decay'. Set type to exponential anyway.", param_config["dist"], ) else: type_ = "uniform" latex = value plot = value return channel, biophys, {"latex": latex, "plot": plot, "type": type_}
[docs] def append_equation(location_map, section, channel, biophys, equation_dict): """Append equation to location map dict. Args: location_map (dict): contains the equations for each channel at each location. To be filled by this function section (str): the section(s) to which the equations should be appended Can be "alldend", "somadend", "somaxon", "allact", "apical", "basal", "axonal" or "somatic" channel (str): name of the channel (ex: "Ca_HVA2") biophys (str): parameter name (ex: "gCa_HVAbar") equation_dict (dict): dictionary containing equation values (for plotting and latex display) and type (uniform or exponential) """ # do not take into account "all" section # set default to create keys then add equations # this allows to either create channel data or append to channel key if section == "alldend": location_map["all dendrites"]["channels"].setdefault( channel, {"equations": {biophys: equation_dict}} ) location_map["all dendrites"]["channels"][channel]["equations"][ biophys ] = equation_dict elif section == "somadend": location_map["all dendrites"]["channels"].setdefault( channel, {"equations": {biophys: equation_dict}} ) location_map["all dendrites"]["channels"][channel]["equations"][ biophys ] = equation_dict location_map["somatic"]["channels"].setdefault( channel, {"equations": {biophys: equation_dict}} ) location_map["somatic"]["channels"][channel]["equations"][ biophys ] = equation_dict elif section == "somaxon": location_map["somatic"]["channels"].setdefault( channel, {"equations": {biophys: equation_dict}} ) location_map["somatic"]["channels"][channel]["equations"][ biophys ] = equation_dict location_map["axonal"]["channels"].setdefault( channel, {"equations": {biophys: equation_dict}} ) location_map["axonal"]["channels"][channel]["equations"][ biophys ] = equation_dict elif section == "allact": location_map["all dendrites"]["channels"].setdefault( channel, {"equations": {biophys: equation_dict}} ) location_map["all dendrites"]["channels"][channel]["equations"][ biophys ] = equation_dict location_map["somatic"]["channels"].setdefault( channel, {"equations": {biophys: equation_dict}} ) location_map["somatic"]["channels"][channel]["equations"][ biophys ] = equation_dict location_map["axonal"]["channels"].setdefault( channel, {"equations": {biophys: equation_dict}} ) location_map["axonal"]["channels"][channel]["equations"][ biophys ] = equation_dict elif section == "apical": location_map["apical"]["channels"].setdefault( channel, {"equations": {biophys: equation_dict}} ) location_map["apical"]["channels"][channel]["equations"][ biophys ] = equation_dict elif section == "basal": location_map["basal"]["channels"].setdefault( channel, {"equations": {biophys: equation_dict}} ) location_map["basal"]["channels"][channel]["equations"][biophys] = equation_dict elif section == "axonal": location_map["axonal"]["channels"].setdefault( channel, {"equations": {biophys: equation_dict}} ) location_map["axonal"]["channels"][channel]["equations"][ biophys ] = equation_dict elif section == "somatic": location_map["somatic"]["channels"].setdefault( channel, {"equations": {biophys: equation_dict}} ) location_map["somatic"]["channels"][channel]["equations"][ biophys ] = equation_dict
[docs] def clean_location_map(location_map): """Remove empty locations. Args: location_map (dict): contains the equations for each channel at each location """ for key, loc in list(location_map.items()): if not loc["channels"]: location_map.pop(key)
[docs] def get_mechanisms_data(emodel, optimized_params_dict, unoptimized_params_dict): """Return a dictionary containing channel mechanisms for each section. Args: emodel (str): name of the emodel optimized_params_dict (dict): contains the optimized parameters unoptimized_params_dict (dict): contains the unoptimized parameters, and also contains the decay and exponential equations Returns: dict: containing the channel mechanisms """ # pylint: disable=too-many-locals release_params = optimized_params_dict[emodel]["params"] decay_func = None if "decay" in unoptimized_params_dict["distributions"].keys(): decay_func = unoptimized_params_dict["distributions"]["decay"]["fun"] parameters = unoptimized_params_dict["parameters"] exp_fun = unoptimized_params_dict["distributions"]["exp"]["fun"] location_map = { "all dendrites": {"channels": {}}, "apical": {"channels": {}}, "basal": {"channels": {}}, "somatic": {"channels": {}}, "axonal": {"channels": {}}, } for section, unoptimized_params_list in parameters.items(): # do not take into account "comment" if isinstance(unoptimized_params_list, list): for param_config in unoptimized_params_list: name = param_config["name"] full_name = ".".join((name, section)) # only take into account parameters present in finals.json if ( full_name in release_params and full_name != "constant.distribution_decay" ): channel, biophys, equation_dict = get_channel_and_equations( name, param_config, full_name, exp_fun, decay_func, release_params, ) # append equation in location map append_equation( location_map, section, channel, biophys, equation_dict ) # remove empty locations clean_location_map(location_map) values = [ { "tooltip": "", "location_map": location_map, "unit": "", "name": "list of ion channel mechanisms", } ] return {"name": "Channel mechanisms", "values": values}