From 09e4bc5e0aa86272ea056f0323c72e0ed0088ef5 Mon Sep 17 00:00:00 2001 From: "Austin E. Soplata" Date: Tue, 2 Sep 2025 12:44:29 -0400 Subject: [PATCH 1/3] example/debug of child-object L5P class This includes disabling of the existing way to create this celltype (calling `pyramidal` which then calls `_cell_L5pyr`), and includes an example script to show that the results output the same. --- hnn_core/cells_default.py | 335 ++++++++++++++++++++++++++----------- hnn_core/network_models.py | 5 +- 2 files changed, 242 insertions(+), 98 deletions(-) diff --git a/hnn_core/cells_default.py b/hnn_core/cells_default.py index 6d3abb095..6f33a8d97 100644 --- a/hnn_core/cells_default.py +++ b/hnn_core/cells_default.py @@ -134,100 +134,100 @@ def _cell_L2Pyr(override_params, pos=(0.0, 0.0, 0), gid=0.0): ) -def _cell_L5Pyr(override_params, pos=(0.0, 0.0, 0), gid=0.0): - """The geometry of the default sections in L5Pyr Neuron.""" - - p_all = get_L5Pyr_params_default() - if override_params is not None: - assert isinstance(override_params, dict) - p_all = compare_dictionaries(p_all, override_params) - - section_names = [ - "apical_trunk", - "apical_1", - "apical_2", - "apical_tuft", - "apical_oblique", - "basal_1", - "basal_2", - "basal_3", - ] - - sections = _get_dends(p_all, cell_type="L5Pyr", section_names=section_names) - sections["soma"] = _get_pyr_soma(p_all, "L5Pyr") - - end_pts = { - "soma": [[0, 0, 0], [0, 0, 23]], - "apical_trunk": [[0, 0, 23], [0, 0, 83]], - "apical_oblique": [[0, 0, 83], [-150, 0, 83]], - "apical_1": [[0, 0, 83], [0, 0, 483]], - "apical_2": [[0, 0, 483], [0, 0, 883]], - "apical_tuft": [[0, 0, 883], [0, 0, 1133]], - "basal_1": [[0, 0, 0], [0, 0, -50]], - "basal_2": [[0, 0, -50], [-106, 0, -156]], - "basal_3": [[0, 0, -50], [106, 0, -156]], - } - - # units = ['pS/um^2', 'S/cm^2', 'pS/um^2', '??', 'tau', '??'] - mechanisms = { - "hh2": ["gkbar_hh2", "gnabar_hh2", "gl_hh2", "el_hh2"], - "ca": ["gbar_ca"], - "cad": ["taur_cad"], - "kca": ["gbar_kca"], - "km": ["gbar_km"], - "cat": ["gbar_cat"], - "ar": ["gbar_ar"], - } - p_mech = _get_mechanisms(p_all, "L5Pyr", ["soma"] + section_names, mechanisms) - - for sec_name, section in sections.items(): - section._end_pts = end_pts[sec_name] - - if sec_name == "soma": - section.syns = ["gabaa", "gabab"] - else: - section.syns = ["ampa", "nmda", "gabaa", "gabab"] - - section.mechs = p_mech[sec_name] - - if sec_name != "soma": - sections[sec_name].mechs["ar"]["gbar_ar"] = partial( - _exp_g_at_dist, zero_val=1e-6, exp_term=3e-3, offset=0.0 - ) - - cell_tree = { - ("apical_trunk", 0): [("apical_trunk", 1)], - ("apical_1", 0): [("apical_1", 1)], - ("apical_2", 0): [("apical_2", 1)], - ("apical_tuft", 0): [("apical_tuft", 1)], - ("apical_oblique", 0): [("apical_oblique", 1)], - ("basal_1", 0): [("basal_1", 1)], - ("basal_2", 0): [("basal_2", 1)], - ("basal_3", 0): [("basal_3", 1)], - # Different sections connected - ("soma", 0): [("soma", 1), ("basal_1", 0)], - ("soma", 1): [("apical_trunk", 0)], - ("apical_trunk", 1): [("apical_1", 0), ("apical_oblique", 0)], - ("apical_1", 1): [("apical_2", 0)], - ("apical_2", 1): [("apical_tuft", 0)], - ("basal_1", 1): [("basal_2", 0), ("basal_3", 0)], - } - - sect_loc = { - "proximal": ["apical_oblique", "basal_2", "basal_3"], - "distal": ["apical_tuft"], - } - - synapses = _get_pyr_syn_props(p_all, "L5Pyr") - return Cell( - "L5Pyr", - pos, - sections=sections, - synapses=synapses, - sect_loc=sect_loc, - cell_tree=cell_tree, - gid=gid, - ) +# def _cell_L5Pyr(override_params, pos=(0.0, 0.0, 0), gid=0.0): +# """The geometry of the default sections in L5Pyr Neuron.""" + +# p_all = get_L5Pyr_params_default() +# if override_params is not None: +# assert isinstance(override_params, dict) +# p_all = compare_dictionaries(p_all, override_params) + +# section_names = [ +# "apical_trunk", +# "apical_1", +# "apical_2", +# "apical_tuft", +# "apical_oblique", +# "basal_1", +# "basal_2", +# "basal_3", +# ] + +# sections = _get_dends(p_all, cell_type="L5Pyr", section_names=section_names) +# sections["soma"] = _get_pyr_soma(p_all, "L5Pyr") + +# end_pts = { +# "soma": [[0, 0, 0], [0, 0, 23]], +# "apical_trunk": [[0, 0, 23], [0, 0, 83]], +# "apical_oblique": [[0, 0, 83], [-150, 0, 83]], +# "apical_1": [[0, 0, 83], [0, 0, 483]], +# "apical_2": [[0, 0, 483], [0, 0, 883]], +# "apical_tuft": [[0, 0, 883], [0, 0, 1133]], +# "basal_1": [[0, 0, 0], [0, 0, -50]], +# "basal_2": [[0, 0, -50], [-106, 0, -156]], +# "basal_3": [[0, 0, -50], [106, 0, -156]], +# } + +# # units = ['pS/um^2', 'S/cm^2', 'pS/um^2', '??', 'tau', '??'] +# mechanisms = { +# "hh2": ["gkbar_hh2", "gnabar_hh2", "gl_hh2", "el_hh2"], +# "ca": ["gbar_ca"], +# "cad": ["taur_cad"], +# "kca": ["gbar_kca"], +# "km": ["gbar_km"], +# "cat": ["gbar_cat"], +# "ar": ["gbar_ar"], +# } +# p_mech = _get_mechanisms(p_all, "L5Pyr", ["soma"] + section_names, mechanisms) + +# for sec_name, section in sections.items(): +# section._end_pts = end_pts[sec_name] + +# if sec_name == "soma": +# section.syns = ["gabaa", "gabab"] +# else: +# section.syns = ["ampa", "nmda", "gabaa", "gabab"] + +# section.mechs = p_mech[sec_name] + +# if sec_name != "soma": +# sections[sec_name].mechs["ar"]["gbar_ar"] = partial( +# _exp_g_at_dist, zero_val=1e-6, exp_term=3e-3, offset=0.0 +# ) + +# cell_tree = { +# ("apical_trunk", 0): [("apical_trunk", 1)], +# ("apical_1", 0): [("apical_1", 1)], +# ("apical_2", 0): [("apical_2", 1)], +# ("apical_tuft", 0): [("apical_tuft", 1)], +# ("apical_oblique", 0): [("apical_oblique", 1)], +# ("basal_1", 0): [("basal_1", 1)], +# ("basal_2", 0): [("basal_2", 1)], +# ("basal_3", 0): [("basal_3", 1)], +# # Different sections connected +# ("soma", 0): [("soma", 1), ("basal_1", 0)], +# ("soma", 1): [("apical_trunk", 0)], +# ("apical_trunk", 1): [("apical_1", 0), ("apical_oblique", 0)], +# ("apical_1", 1): [("apical_2", 0)], +# ("apical_2", 1): [("apical_tuft", 0)], +# ("basal_1", 1): [("basal_2", 0), ("basal_3", 0)], +# } + +# sect_loc = { +# "proximal": ["apical_oblique", "basal_2", "basal_3"], +# "distal": ["apical_tuft"], +# } + +# synapses = _get_pyr_syn_props(p_all, "L5Pyr") +# return Cell( +# "L5Pyr", +# pos, +# sections=sections, +# synapses=synapses, +# sect_loc=sect_loc, +# cell_tree=cell_tree, +# gid=gid, +# ) def _get_basket_soma(cell_name): @@ -384,8 +384,8 @@ def pyramidal(cell_name, pos=(0, 0, 0), override_params=None, gid=None): """ if cell_name == "L2_pyramidal": return _cell_L2Pyr(override_params, pos=pos, gid=gid) - elif cell_name == "L5_pyramidal": - return _cell_L5Pyr(override_params, pos=pos, gid=gid) + # elif cell_name == "L5_pyramidal": + # return _cell_L5Pyr(override_params, pos=pos, gid=gid) else: raise ValueError(f"Unknown pyramidal cell type: {cell_name}") @@ -442,3 +442,146 @@ def pyramidal_ca(cell_name, pos, override_params=None, gid=None): cell = pyramidal(cell_name, pos, override_params=override_params, gid=gid) return cell + + +class L5_pyramidal_cell(Cell): + # AES: arguments were changed to match that of `pyramidal` function, NOT + # `_cell_L5pyr`, which were invalid! + def __init__(self, override_params=None, pos=(0, 0, 0), gid=None): + """TODO: This child-class of Cell can act as a full replacement for `pyramidal(cell_name='L5_pyramidal')`.""" + + # AES: Everything below, until said otherwise, has been copied without + # modification from function `_cell_L5Pyr` above: + + p_all = get_L5Pyr_params_default() + if override_params is not None: + assert isinstance(override_params, dict) + p_all = compare_dictionaries(p_all, override_params) + + section_names = [ + "apical_trunk", + "apical_1", + "apical_2", + "apical_tuft", + "apical_oblique", + "basal_1", + "basal_2", + "basal_3", + ] + + sections = _get_dends(p_all, cell_type="L5Pyr", section_names=section_names) + sections["soma"] = _get_pyr_soma(p_all, "L5Pyr") + + end_pts = { + "soma": [[0, 0, 0], [0, 0, 23]], + "apical_trunk": [[0, 0, 23], [0, 0, 83]], + "apical_oblique": [[0, 0, 83], [-150, 0, 83]], + "apical_1": [[0, 0, 83], [0, 0, 483]], + "apical_2": [[0, 0, 483], [0, 0, 883]], + "apical_tuft": [[0, 0, 883], [0, 0, 1133]], + "basal_1": [[0, 0, 0], [0, 0, -50]], + "basal_2": [[0, 0, -50], [-106, 0, -156]], + "basal_3": [[0, 0, -50], [106, 0, -156]], + } + + # units = ['pS/um^2', 'S/cm^2', 'pS/um^2', '??', 'tau', '??'] + mechanisms = { + "hh2": ["gkbar_hh2", "gnabar_hh2", "gl_hh2", "el_hh2"], + "ca": ["gbar_ca"], + "cad": ["taur_cad"], + "kca": ["gbar_kca"], + "km": ["gbar_km"], + "cat": ["gbar_cat"], + "ar": ["gbar_ar"], + } + p_mech = _get_mechanisms(p_all, "L5Pyr", ["soma"] + section_names, mechanisms) + + for sec_name, section in sections.items(): + section._end_pts = end_pts[sec_name] + + if sec_name == "soma": + section.syns = ["gabaa", "gabab"] + else: + section.syns = ["ampa", "nmda", "gabaa", "gabab"] + + section.mechs = p_mech[sec_name] + + if sec_name != "soma": + sections[sec_name].mechs["ar"]["gbar_ar"] = partial( + _exp_g_at_dist, zero_val=1e-6, exp_term=3e-3, offset=0.0 + ) + + cell_tree = { + ("apical_trunk", 0): [("apical_trunk", 1)], + ("apical_1", 0): [("apical_1", 1)], + ("apical_2", 0): [("apical_2", 1)], + ("apical_tuft", 0): [("apical_tuft", 1)], + ("apical_oblique", 0): [("apical_oblique", 1)], + ("basal_1", 0): [("basal_1", 1)], + ("basal_2", 0): [("basal_2", 1)], + ("basal_3", 0): [("basal_3", 1)], + # Different sections connected + ("soma", 0): [("soma", 1), ("basal_1", 0)], + ("soma", 1): [("apical_trunk", 0)], + ("apical_trunk", 1): [("apical_1", 0), ("apical_oblique", 0)], + ("apical_1", 1): [("apical_2", 0)], + ("apical_2", 1): [("apical_tuft", 0)], + ("basal_1", 1): [("basal_2", 0), ("basal_3", 0)], + } + + sect_loc = { + "proximal": ["apical_oblique", "basal_2", "basal_3"], + "distal": ["apical_tuft"], + } + + synapses = _get_pyr_syn_props(p_all, "L5Pyr") + # return Cell( + # "L5Pyr", + # pos, + # sections=sections, + # synapses=synapses, + # sect_loc=sect_loc, + # cell_tree=cell_tree, + # gid=gid, + # ) + + # AES: This is the end of the copied body of `_cell_L5Pyr`. + + name = "L5Pyr" # AES: This is the only new line needed + + # AES: This is the beginning of the body of `Cell.__init__` copied without + # modification: + self.name = name + self.pos = pos + for section in sections.values(): + if not isinstance(section, Section): + raise ValueError( + f"Items in section must be instances" + f" of Section. Got {type(section)}" + ) + self.sections = sections + self.synapses = synapses + self.sect_loc = sect_loc + self._nrn_sections = dict() + self._nrn_synapses = dict() + self.dipole_pp = list() + self.vsec = dict() + self.isec = dict() + self.ca = dict() + # insert iclamp + self.list_IClamp = list() + self._gid = None + self.tonic_biases = list() + if gid is not None: + self.gid = gid # use setter method to check input argument gid + + # Store the tree representation of the cell + self.cell_tree = cell_tree + + self._update_end_pts() # New implementation + + self._compute_section_mechs() # Set mech values of all sections + + # AES: This is the end of the body of `Cell.__init__` copied without + # modification. + diff --git a/hnn_core/network_models.py b/hnn_core/network_models.py index b775d5bf7..c1a5c7add 100644 --- a/hnn_core/network_models.py +++ b/hnn_core/network_models.py @@ -7,7 +7,7 @@ from hnn_core import read_params from .network import Network, _create_cell_coords from .params import _short_name -from .cells_default import pyramidal_ca, pyramidal, basket +from .cells_default import pyramidal_ca, pyramidal, basket, L5_pyramidal_cell from .externals.mne import _validate_type # ToDO -> direct _cell_L2Pyr calling @@ -107,7 +107,8 @@ def jones_2009_model( }, }, "L5_pyramidal": { - "cell_object": pyramidal(cell_name="L5_pyramidal"), + # "cell_object": pyramidal(cell_name="L5_pyramidal"), + "cell_object": L5_pyramidal_cell(), "cell_metadata": { "morpho_type": "pyramidal", "electro_type": "excitatory", From c487760b19aa7fe3d6a3aa0341a3f553d4fe0aac Mon Sep 17 00:00:00 2001 From: Chetank99 Date: Wed, 17 Sep 2025 07:35:17 +0000 Subject: [PATCH 2/3] built on Austin's foundations to refac cell types with super introduced --- hnn_core/cells_default.py | 277 ++++++++++++++++++++++++------------- hnn_core/network_models.py | 12 +- 2 files changed, 191 insertions(+), 98 deletions(-) diff --git a/hnn_core/cells_default.py b/hnn_core/cells_default.py index 6f33a8d97..f520eff5e 100644 --- a/hnn_core/cells_default.py +++ b/hnn_core/cells_default.py @@ -52,7 +52,7 @@ def _get_pyr_soma(p_all, cell_type): Ra=p_all[f"{cell_type}_soma_Ra"], ) - +''' def _cell_L2Pyr(override_params, pos=(0.0, 0.0, 0), gid=0.0): """The geometry of the default sections in L2Pyr neuron.""" p_all = get_L2Pyr_params_default() @@ -132,7 +132,7 @@ def _cell_L2Pyr(override_params, pos=(0.0, 0.0, 0), gid=0.0): cell_tree=cell_tree, gid=gid, ) - +''' # def _cell_L5Pyr(override_params, pos=(0.0, 0.0, 0), gid=0.0): # """The geometry of the default sections in L5Pyr Neuron.""" @@ -342,29 +342,12 @@ def basket(cell_name, pos=(0, 0, 0), gid=None): The basket cell. """ if cell_name == "L2_basket": - sect_loc = dict(proximal=["soma"], distal=["soma"]) + return L2_basket_cell(pos=pos, gid=gid) elif cell_name == "L5_basket": - sect_loc = dict(proximal=["soma"], distal=[]) + return L5_basket_cell(pos=pos, gid=gid) else: raise ValueError(f"Unknown basket cell type: {cell_name}") - sections = dict() - sections["soma"] = _get_basket_soma(cell_name) - synapses = _get_basket_syn_props() - sections["soma"].syns = list(synapses.keys()) - sections["soma"].mechs = {"hh2": dict()} - - cell_tree = None - return Cell( - cell_name, - pos, - sections=sections, - synapses=synapses, - sect_loc=sect_loc, - cell_tree=cell_tree, - gid=gid, - ) - def pyramidal(cell_name, pos=(0, 0, 0), override_params=None, gid=None): """Pyramidal neuron. @@ -383,9 +366,9 @@ def pyramidal(cell_name, pos=(0, 0, 0), override_params=None, gid=None): yet attached to a network. Once the GID is set, it cannot be changed. """ if cell_name == "L2_pyramidal": - return _cell_L2Pyr(override_params, pos=pos, gid=gid) - # elif cell_name == "L5_pyramidal": - # return _cell_L5Pyr(override_params, pos=pos, gid=gid) + return L2_pyramidal_cell(override_params, pos=pos, gid=gid) + elif cell_name == "L5_pyramidal": + return L5_pyramidal_cell(override_params=override_params, pos=pos, gid=gid) else: raise ValueError(f"Unknown pyramidal cell type: {cell_name}") @@ -443,21 +426,28 @@ def pyramidal_ca(cell_name, pos, override_params=None, gid=None): return cell - class L5_pyramidal_cell(Cell): - # AES: arguments were changed to match that of `pyramidal` function, NOT - # `_cell_L5pyr`, which were invalid! - def __init__(self, override_params=None, pos=(0, 0, 0), gid=None): - """TODO: This child-class of Cell can act as a full replacement for `pyramidal(cell_name='L5_pyramidal')`.""" - - # AES: Everything below, until said otherwise, has been copied without - # modification from function `_cell_L5Pyr` above: - + """L5 pyramidal cell implemented as a Cell subclass.""" + + def __init__(self, override_params=None, pos=(0.0, 0.0, 0), gid=None): + """Initialize L5 pyramidal cell. + + Parameters + ---------- + override_params : dict or None + Parameters to override the default set + pos : tuple + Coordinates of cell soma in xyz-space + gid : int or None + Global ID of the cell + """ + # Get default parameters p_all = get_L5Pyr_params_default() if override_params is not None: assert isinstance(override_params, dict) p_all = compare_dictionaries(p_all, override_params) - + + # Define sections section_names = [ "apical_trunk", "apical_1", @@ -468,10 +458,11 @@ def __init__(self, override_params=None, pos=(0, 0, 0), gid=None): "basal_2", "basal_3", ] - + sections = _get_dends(p_all, cell_type="L5Pyr", section_names=section_names) sections["soma"] = _get_pyr_soma(p_all, "L5Pyr") - + + # Define endpoints end_pts = { "soma": [[0, 0, 0], [0, 0, 23]], "apical_trunk": [[0, 0, 23], [0, 0, 83]], @@ -483,8 +474,8 @@ def __init__(self, override_params=None, pos=(0, 0, 0), gid=None): "basal_2": [[0, 0, -50], [-106, 0, -156]], "basal_3": [[0, 0, -50], [106, 0, -156]], } - - # units = ['pS/um^2', 'S/cm^2', 'pS/um^2', '??', 'tau', '??'] + + # Define mechanisms mechanisms = { "hh2": ["gkbar_hh2", "gnabar_hh2", "gl_hh2", "el_hh2"], "ca": ["gbar_ca"], @@ -495,22 +486,24 @@ def __init__(self, override_params=None, pos=(0, 0, 0), gid=None): "ar": ["gbar_ar"], } p_mech = _get_mechanisms(p_all, "L5Pyr", ["soma"] + section_names, mechanisms) - + + # Configure sections for sec_name, section in sections.items(): section._end_pts = end_pts[sec_name] - + if sec_name == "soma": section.syns = ["gabaa", "gabab"] else: section.syns = ["ampa", "nmda", "gabaa", "gabab"] - + section.mechs = p_mech[sec_name] - + if sec_name != "soma": sections[sec_name].mechs["ar"]["gbar_ar"] = partial( _exp_g_at_dist, zero_val=1e-6, exp_term=3e-3, offset=0.0 ) - + + # Define cell tree cell_tree = { ("apical_trunk", 0): [("apical_trunk", 1)], ("apical_1", 0): [("apical_1", 1)], @@ -528,60 +521,158 @@ def __init__(self, override_params=None, pos=(0, 0, 0), gid=None): ("apical_2", 1): [("apical_tuft", 0)], ("basal_1", 1): [("basal_2", 0), ("basal_3", 0)], } + + # Define section locations + sect_loc = { + "proximal": ["apical_oblique", "basal_2", "basal_3"], + "distal": ["apical_tuft"], + } + + # Get synapses + synapses = _get_pyr_syn_props(p_all, "L5Pyr") + + # Call parent constructor + super().__init__( + "L5Pyr", + pos, + sections=sections, + synapses=synapses, + sect_loc=sect_loc, + cell_tree=cell_tree, + gid=gid + ) +class L2_pyramidal_cell(Cell): + """L2 pyramidal cell implemented as a Cell subclass.""" + + def __init__(self, override_params=None, pos=(0.0, 0.0, 0), gid=None): + """Initialize L2 pyramidal cell.""" + + p_all = get_L2Pyr_params_default() + if override_params is not None: + assert isinstance(override_params, dict) + p_all = compare_dictionaries(p_all, override_params) + + section_names = [ + "apical_trunk", + "apical_1", + "apical_tuft", + "apical_oblique", + "basal_1", + "basal_2", + "basal_3", + ] + + sections = _get_dends(p_all, cell_type="L2Pyr", section_names=section_names) + sections["soma"] = _get_pyr_soma(p_all, "L2Pyr") + + end_pts = { + "soma": [[-50, 0, 765], [-50, 0, 778]], + "apical_trunk": [[-50, 0, 778], [-50, 0, 813]], + "apical_oblique": [[-50, 0, 813], [-250, 0, 813]], + "apical_1": [[-50, 0, 813], [-50, 0, 993]], + "apical_tuft": [[-50, 0, 993], [-50, 0, 1133]], + "basal_1": [[-50, 0, 765], [-50, 0, 715]], + "basal_2": [[-50, 0, 715], [-156, 0, 609]], + "basal_3": [[-50, 0, 715], [56, 0, 609]], + } + + mechanisms = { + "km": ["gbar_km"], + "hh2": ["gkbar_hh2", "gnabar_hh2", "gl_hh2", "el_hh2"], + } + p_mech = _get_mechanisms(p_all, "L2Pyr", ["soma"] + section_names, mechanisms) + + for sec_name, section in sections.items(): + section._end_pts = end_pts[sec_name] + + if sec_name == "soma": + section.syns = ["gabaa", "gabab"] + else: + section.syns = ["ampa", "nmda", "gabaa", "gabab"] + + section.mechs = p_mech[sec_name] + + cell_tree = { + ("apical_trunk", 0): [("apical_trunk", 1)], + ("apical_1", 0): [("apical_1", 1)], + ("apical_tuft", 0): [("apical_tuft", 1)], + ("apical_oblique", 0): [("apical_oblique", 1)], + ("basal_1", 0): [("basal_1", 1)], + ("basal_2", 0): [("basal_2", 1)], + ("basal_3", 0): [("basal_3", 1)], + ("soma", 0): [("soma", 1), ("basal_1", 0)], + ("soma", 1): [("apical_trunk", 0)], + ("apical_trunk", 1): [("apical_1", 0), ("apical_oblique", 0)], + ("apical_1", 1): [("apical_tuft", 0)], + ("basal_1", 1): [("basal_2", 0), ("basal_3", 0)], + } + sect_loc = { "proximal": ["apical_oblique", "basal_2", "basal_3"], "distal": ["apical_tuft"], } + + synapses = _get_pyr_syn_props(p_all, "L2Pyr") + + super().__init__( + "L2Pyr", + pos, + sections=sections, + synapses=synapses, + sect_loc=sect_loc, + cell_tree=cell_tree, + gid=gid + ) - synapses = _get_pyr_syn_props(p_all, "L5Pyr") - # return Cell( - # "L5Pyr", - # pos, - # sections=sections, - # synapses=synapses, - # sect_loc=sect_loc, - # cell_tree=cell_tree, - # gid=gid, - # ) - - # AES: This is the end of the copied body of `_cell_L5Pyr`. - - name = "L5Pyr" # AES: This is the only new line needed - - # AES: This is the beginning of the body of `Cell.__init__` copied without - # modification: - self.name = name - self.pos = pos - for section in sections.values(): - if not isinstance(section, Section): - raise ValueError( - f"Items in section must be instances" - f" of Section. Got {type(section)}" - ) - self.sections = sections - self.synapses = synapses - self.sect_loc = sect_loc - self._nrn_sections = dict() - self._nrn_synapses = dict() - self.dipole_pp = list() - self.vsec = dict() - self.isec = dict() - self.ca = dict() - # insert iclamp - self.list_IClamp = list() - self._gid = None - self.tonic_biases = list() - if gid is not None: - self.gid = gid # use setter method to check input argument gid - - # Store the tree representation of the cell - self.cell_tree = cell_tree - - self._update_end_pts() # New implementation - - self._compute_section_mechs() # Set mech values of all sections - - # AES: This is the end of the body of `Cell.__init__` copied without - # modification. +class L2_basket_cell(Cell): + """L2 basket cell implemented as a Cell subclass.""" + + def __init__(self, pos=(0, 0, 0), gid=None): + """Initialize L2 basket cell.""" + + sections = dict() + sections["soma"] = _get_basket_soma("L2_basket") + synapses = _get_basket_syn_props() + sections["soma"].syns = list(synapses.keys()) + sections["soma"].mechs = {"hh2": dict()} + + sect_loc = dict(proximal=["soma"], distal=["soma"]) + cell_tree = None + + super().__init__( + "L2_basket", + pos, + sections=sections, + synapses=synapses, + sect_loc=sect_loc, + cell_tree=cell_tree, + gid=gid + ) + + +class L5_basket_cell(Cell): + """L5 basket cell implemented as a Cell subclass.""" + + def __init__(self, pos=(0, 0, 0), gid=None): + """Initialize L5 basket cell.""" + + sections = dict() + sections["soma"] = _get_basket_soma("L5_basket") + synapses = _get_basket_syn_props() + sections["soma"].syns = list(synapses.keys()) + sections["soma"].mechs = {"hh2": dict()} + + sect_loc = dict(proximal=["soma"], distal=[]) + cell_tree = None + + super().__init__( + "L5_basket", + pos, + sections=sections, + synapses=synapses, + sect_loc=sect_loc, + cell_tree=cell_tree, + gid=gid + ) diff --git a/hnn_core/network_models.py b/hnn_core/network_models.py index c1a5c7add..dbe780dd0 100644 --- a/hnn_core/network_models.py +++ b/hnn_core/network_models.py @@ -7,7 +7,9 @@ from hnn_core import read_params from .network import Network, _create_cell_coords from .params import _short_name -from .cells_default import pyramidal_ca, pyramidal, basket, L5_pyramidal_cell +from .cells_default import (pyramidal_ca, pyramidal, basket, + L5_pyramidal_cell, L2_pyramidal_cell, + L5_basket_cell, L2_basket_cell) from .externals.mne import _validate_type # ToDO -> direct _cell_L2Pyr calling @@ -77,7 +79,7 @@ def jones_2009_model( # data is here in metaData format cell_types = { "L2_basket": { - "cell_object": basket(cell_name="L2_basket"), + "cell_object": L2_basket_cell(), "cell_metadata": { "morpho_type": "basket", "electro_type": "inhibitory", @@ -87,7 +89,7 @@ def jones_2009_model( }, }, "L2_pyramidal": { - "cell_object": pyramidal(cell_name="L2_pyramidal"), + "cell_object": L2_pyramidal_cell(), "cell_metadata": { "morpho_type": "pyramidal", "electro_type": "excitatory", @@ -97,7 +99,7 @@ def jones_2009_model( }, }, "L5_basket": { - "cell_object": basket(cell_name="L5_basket"), + "cell_object": L5_basket_cell(), "cell_metadata": { "morpho_type": "basket", "electro_type": "inhibitory", @@ -485,4 +487,4 @@ def add_erp_drives_to_jones_model(net, tstart=0.0): location="proximal", synaptic_delays=synaptic_delays_prox, event_seed=814, - ) + ) \ No newline at end of file From 9614311646d66a96ecfd1ac442942020a7be6618 Mon Sep 17 00:00:00 2001 From: Chetank99 Date: Tue, 23 Sep 2025 11:59:51 +0000 Subject: [PATCH 3/3] ruff --- hnn_core/cells_default.py | 84 ++++++++++++++++++++------------------ hnn_core/network_models.py | 12 ++++-- 2 files changed, 52 insertions(+), 44 deletions(-) diff --git a/hnn_core/cells_default.py b/hnn_core/cells_default.py index f520eff5e..a94a665aa 100644 --- a/hnn_core/cells_default.py +++ b/hnn_core/cells_default.py @@ -52,6 +52,7 @@ def _get_pyr_soma(p_all, cell_type): Ra=p_all[f"{cell_type}_soma_Ra"], ) + ''' def _cell_L2Pyr(override_params, pos=(0.0, 0.0, 0), gid=0.0): """The geometry of the default sections in L2Pyr neuron.""" @@ -426,12 +427,14 @@ def pyramidal_ca(cell_name, pos, override_params=None, gid=None): return cell + +# only added comments to L5_pyramidal to convey the logic which i discussed in the last meeting, will remove those and this comment in later commits class L5_pyramidal_cell(Cell): """L5 pyramidal cell implemented as a Cell subclass.""" - + def __init__(self, override_params=None, pos=(0.0, 0.0, 0), gid=None): """Initialize L5 pyramidal cell. - + Parameters ---------- override_params : dict or None @@ -446,7 +449,7 @@ def __init__(self, override_params=None, pos=(0.0, 0.0, 0), gid=None): if override_params is not None: assert isinstance(override_params, dict) p_all = compare_dictionaries(p_all, override_params) - + # Define sections section_names = [ "apical_trunk", @@ -458,10 +461,10 @@ def __init__(self, override_params=None, pos=(0.0, 0.0, 0), gid=None): "basal_2", "basal_3", ] - + sections = _get_dends(p_all, cell_type="L5Pyr", section_names=section_names) sections["soma"] = _get_pyr_soma(p_all, "L5Pyr") - + # Define endpoints end_pts = { "soma": [[0, 0, 0], [0, 0, 23]], @@ -474,7 +477,7 @@ def __init__(self, override_params=None, pos=(0.0, 0.0, 0), gid=None): "basal_2": [[0, 0, -50], [-106, 0, -156]], "basal_3": [[0, 0, -50], [106, 0, -156]], } - + # Define mechanisms mechanisms = { "hh2": ["gkbar_hh2", "gnabar_hh2", "gl_hh2", "el_hh2"], @@ -486,23 +489,23 @@ def __init__(self, override_params=None, pos=(0.0, 0.0, 0), gid=None): "ar": ["gbar_ar"], } p_mech = _get_mechanisms(p_all, "L5Pyr", ["soma"] + section_names, mechanisms) - + # Configure sections for sec_name, section in sections.items(): section._end_pts = end_pts[sec_name] - + if sec_name == "soma": section.syns = ["gabaa", "gabab"] else: section.syns = ["ampa", "nmda", "gabaa", "gabab"] - + section.mechs = p_mech[sec_name] - + if sec_name != "soma": sections[sec_name].mechs["ar"]["gbar_ar"] = partial( _exp_g_at_dist, zero_val=1e-6, exp_term=3e-3, offset=0.0 ) - + # Define cell tree cell_tree = { ("apical_trunk", 0): [("apical_trunk", 1)], @@ -521,16 +524,16 @@ def __init__(self, override_params=None, pos=(0.0, 0.0, 0), gid=None): ("apical_2", 1): [("apical_tuft", 0)], ("basal_1", 1): [("basal_2", 0), ("basal_3", 0)], } - + # Define section locations sect_loc = { "proximal": ["apical_oblique", "basal_2", "basal_3"], "distal": ["apical_tuft"], } - + # Get synapses synapses = _get_pyr_syn_props(p_all, "L5Pyr") - + # Call parent constructor super().__init__( "L5Pyr", @@ -539,20 +542,21 @@ def __init__(self, override_params=None, pos=(0.0, 0.0, 0), gid=None): synapses=synapses, sect_loc=sect_loc, cell_tree=cell_tree, - gid=gid + gid=gid, ) + class L2_pyramidal_cell(Cell): """L2 pyramidal cell implemented as a Cell subclass.""" - + def __init__(self, override_params=None, pos=(0.0, 0.0, 0), gid=None): """Initialize L2 pyramidal cell.""" - + p_all = get_L2Pyr_params_default() if override_params is not None: assert isinstance(override_params, dict) p_all = compare_dictionaries(p_all, override_params) - + section_names = [ "apical_trunk", "apical_1", @@ -562,10 +566,10 @@ def __init__(self, override_params=None, pos=(0.0, 0.0, 0), gid=None): "basal_2", "basal_3", ] - + sections = _get_dends(p_all, cell_type="L2Pyr", section_names=section_names) sections["soma"] = _get_pyr_soma(p_all, "L2Pyr") - + end_pts = { "soma": [[-50, 0, 765], [-50, 0, 778]], "apical_trunk": [[-50, 0, 778], [-50, 0, 813]], @@ -576,23 +580,23 @@ def __init__(self, override_params=None, pos=(0.0, 0.0, 0), gid=None): "basal_2": [[-50, 0, 715], [-156, 0, 609]], "basal_3": [[-50, 0, 715], [56, 0, 609]], } - + mechanisms = { "km": ["gbar_km"], "hh2": ["gkbar_hh2", "gnabar_hh2", "gl_hh2", "el_hh2"], } p_mech = _get_mechanisms(p_all, "L2Pyr", ["soma"] + section_names, mechanisms) - + for sec_name, section in sections.items(): section._end_pts = end_pts[sec_name] - + if sec_name == "soma": section.syns = ["gabaa", "gabab"] else: section.syns = ["ampa", "nmda", "gabaa", "gabab"] - + section.mechs = p_mech[sec_name] - + cell_tree = { ("apical_trunk", 0): [("apical_trunk", 1)], ("apical_1", 0): [("apical_1", 1)], @@ -607,14 +611,14 @@ def __init__(self, override_params=None, pos=(0.0, 0.0, 0), gid=None): ("apical_1", 1): [("apical_tuft", 0)], ("basal_1", 1): [("basal_2", 0), ("basal_3", 0)], } - + sect_loc = { "proximal": ["apical_oblique", "basal_2", "basal_3"], "distal": ["apical_tuft"], } - + synapses = _get_pyr_syn_props(p_all, "L2Pyr") - + super().__init__( "L2Pyr", pos, @@ -622,24 +626,25 @@ def __init__(self, override_params=None, pos=(0.0, 0.0, 0), gid=None): synapses=synapses, sect_loc=sect_loc, cell_tree=cell_tree, - gid=gid + gid=gid, ) + class L2_basket_cell(Cell): """L2 basket cell implemented as a Cell subclass.""" - + def __init__(self, pos=(0, 0, 0), gid=None): """Initialize L2 basket cell.""" - + sections = dict() sections["soma"] = _get_basket_soma("L2_basket") synapses = _get_basket_syn_props() sections["soma"].syns = list(synapses.keys()) sections["soma"].mechs = {"hh2": dict()} - + sect_loc = dict(proximal=["soma"], distal=["soma"]) cell_tree = None - + super().__init__( "L2_basket", pos, @@ -647,25 +652,25 @@ def __init__(self, pos=(0, 0, 0), gid=None): synapses=synapses, sect_loc=sect_loc, cell_tree=cell_tree, - gid=gid + gid=gid, ) class L5_basket_cell(Cell): """L5 basket cell implemented as a Cell subclass.""" - + def __init__(self, pos=(0, 0, 0), gid=None): """Initialize L5 basket cell.""" - + sections = dict() sections["soma"] = _get_basket_soma("L5_basket") synapses = _get_basket_syn_props() sections["soma"].syns = list(synapses.keys()) sections["soma"].mechs = {"hh2": dict()} - + sect_loc = dict(proximal=["soma"], distal=[]) cell_tree = None - + super().__init__( "L5_basket", pos, @@ -673,6 +678,5 @@ def __init__(self, pos=(0, 0, 0), gid=None): synapses=synapses, sect_loc=sect_loc, cell_tree=cell_tree, - gid=gid + gid=gid, ) - diff --git a/hnn_core/network_models.py b/hnn_core/network_models.py index dbe780dd0..8f774ee52 100644 --- a/hnn_core/network_models.py +++ b/hnn_core/network_models.py @@ -7,9 +7,13 @@ from hnn_core import read_params from .network import Network, _create_cell_coords from .params import _short_name -from .cells_default import (pyramidal_ca, pyramidal, basket, - L5_pyramidal_cell, L2_pyramidal_cell, - L5_basket_cell, L2_basket_cell) +from .cells_default import ( + pyramidal_ca, + L5_pyramidal_cell, + L2_pyramidal_cell, + L5_basket_cell, + L2_basket_cell, +) from .externals.mne import _validate_type # ToDO -> direct _cell_L2Pyr calling @@ -487,4 +491,4 @@ def add_erp_drives_to_jones_model(net, tstart=0.0): location="proximal", synaptic_delays=synaptic_delays_prox, event_seed=814, - ) \ No newline at end of file + )