Source code for bluecellulab.cell.section_tools

# Copyright 2025 Open Brain Institute

# 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.
"""NEURON section helpers for BlueCelluLab."""


[docs] def currents_vars(section) -> dict: """Return recordable currents (with units) at a given section. - Ionic currents from the ions block (e.g. ``ina``, ``ik``, ``ica``), in mA/cm². - Mechanism currents for variables ``i`` or ``ihcn``, reported as ``<var>_<mech>`` (e.g. ``i_pas``, ``ihcn_Ih``), in mA/cm². Args: section: NEURON Section object. Returns: dict mapping variable names to {"units": str, "kind": str}. """ psec = section.psection() out = {} ions = psec.get("ions", {}) or {} for ion, vars_dict in ions.items(): if ion == "ttx": continue name = f"i{ion}" if name in vars_dict: out[name] = {"units": "mA/cm²", "kind": "ionic_current"} special_currents = { ("pas", "i"): "i_pas", ("Ih", "ihcn"): "ihcn_Ih", ("hd", "i"): "i_hd", } for (mech, var), out_name in special_currents.items(): if var in (psec.get("density_mechs") or {}).get(mech, {}): out[out_name] = {"units": "mA/cm²", "kind": "nonspecific_current"} return dict(sorted(out.items()))
[docs] def mechs_vars(section, include_point_mechs: bool = False) -> dict: """Return mechanism-scoped variables at a given section. Args: section: NEURON Section object. include_point_mechs: Whether to include point processes. """ psec = section.psection() dens = psec.get("density_mechs", {}) or {} points = psec.get("point_mechs", {}) or {} mech_map = { mech: sorted(vars_dict.keys()) for mech, vars_dict in dens.items() if vars_dict } entry = {"mech": mech_map} if include_point_mechs: point_map = { pp: sorted(vars_dict.keys()) for pp, vars_dict in points.items() if vars_dict } entry["point"] = point_map return entry
[docs] def section_to_variable_recording_str(section, segx: float, variable: str) -> str: """Build an evaluable NEURON pointer string for `add_recording`. Accepts: - top-level vars: "v", "ina", "ik", ... - mechanism-scoped vars: "kca.gkca", "na3.m", "na3.h", ... Returns examples: neuron.h.soma[0](0.5)._ref_v neuron.h.soma[0](0.5)._ref_ina neuron.h.soma[0](0.5).kca._ref_gkca neuron.h.dend[3](0.7).na3._ref_m """ sec_name = section.name() if "." in variable: mech, var = variable.split(".", 1) return f"neuron.h.{sec_name}({segx}).{mech}._ref_{var}" else: return f"neuron.h.{sec_name}({segx})._ref_{variable}"