Skip to content

Commit

Permalink
[MRG] Add name parameter to tonic bias and add tonic biases to differ…
Browse files Browse the repository at this point in the history
…ent sections (#922)

* tonic bias options

* update defaults

* describe new parameters

* stop tracking arm64

* flake8

* unit tests

* change sect_name to section for consistency

* change sect_name to section for consistency test_gui

* workaround backwards compatibility

* change CSD back

* add deprecation warning

* fix typos

* unit tests

* clean up section warning

* refactor: changed the default value from None to 'soma'

* chore: updated test asset with section attributes in external_biases

* chore: removed 'section' from ignore_keys in test_gui.check_equal_networks

* fix test

* add bias_name test

* update value error

* fix regex test

* Update hnn_core/tests/test_network.py

Co-authored-by: Mainak Jas <[email protected]>

* Update hnn_core/tests/test_network.py

Co-authored-by: Mainak Jas <[email protected]>

* Update hnn_core/tests/test_network.py

Co-authored-by: Mainak Jas <[email protected]>

* Update hnn_core/network.py

Co-authored-by: Mainak Jas <[email protected]>

* Update hnn_core/network.py

Co-authored-by: Mainak Jas <[email protected]>

* update whats_new and fix flake8

* update whats_new

---------

Co-authored-by: George Dang <[email protected]>
Co-authored-by: Mainak Jas <[email protected]>
  • Loading branch information
3 people authored Jan 10, 2025
1 parent 3901e71 commit 2a82933
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 21 deletions.
4 changes: 4 additions & 0 deletions doc/whats_new.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ API
- Add :func:`~hnn_core.CellResponse.spike_times_by_type` to get cell spiking times
organized by cell type, by `Mainak Jas`_ in :gh:`916`.

- Add option to apply a tonic bias to any compartment of the cell, and option to
add multiple biases per simulation and cell :func:`hnn_core.network.add_tonic_bias`,
by `Katharina Duecker`_ in :gh:`922`.

.. _0.4:

0.4
Expand Down
12 changes: 8 additions & 4 deletions hnn_core/cell.py
Original file line number Diff line number Diff line change
Expand Up @@ -728,8 +728,9 @@ def _insert_dipole(self, sec_name_apical):
dpp.ztan = seg_lens_z[-1]
self.dipole = h.Vector().record(self.dpl_ref)

def create_tonic_bias(self, amplitude, t0, tstop, loc=0.5):
"""Create tonic bias at the soma.
def create_tonic_bias(self, amplitude, t0, tstop, section='soma',
loc=0.5):
"""Create tonic bias at defined section.
Parameters
----------
Expand All @@ -739,10 +740,13 @@ def create_tonic_bias(self, amplitude, t0, tstop, loc=0.5):
The start time of tonic input (in ms).
tstop : float
The end time of tonic input (in ms).
section : str
Section tonic input is applied to.
loc : float (0 to 1)
The location of the input in the soma section.
The location of the input in the section.
"""
stim = h.IClamp(self._nrn_sections['soma'](loc))

stim = h.IClamp(self._nrn_sections[section](loc))
stim.delay = t0
stim.dur = tstop - t0
stim.amp = amplitude
Expand Down
36 changes: 28 additions & 8 deletions hnn_core/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -1133,7 +1133,8 @@ def _instantiate_drives(self, tstop, n_trials=1):
self.external_drives[
drive['name']]['events'].append(event_times)

def add_tonic_bias(self, *, cell_type=None, amplitude, t0=0, tstop=None):
def add_tonic_bias(self, *, cell_type=None, section='soma',
bias_name='tonic', amplitude, t0=0, tstop=None):
"""Attaches parameters of tonic bias input for given cell types
Parameters
Expand All @@ -1142,6 +1143,11 @@ def add_tonic_bias(self, *, cell_type=None, amplitude, t0=0, tstop=None):
The name of the cell type to add a tonic input. When supplied,
a float value must be provided with the `amplitude` keyword.
Valid inputs are those listed in `net.cell_types`.
section : str
name of cell section the bias should be applied to.
See net.cell_types[cell_type].sections.keys()
bias_name : str
The name of the bias.
amplitude: dict | float
A dictionary of cell type keys (str) to amplitude values (float).
Valid inputs for cell types are those listed in `net.cell_types`.
Expand Down Expand Up @@ -1169,6 +1175,7 @@ def add_tonic_bias(self, *, cell_type=None, amplitude, t0=0, tstop=None):
_validate_type(amplitude, (float, int), 'amplitude')

_add_cell_type_bias(network=self, cell_type=cell_type,
section=section, bias_name=bias_name,
amplitude=float(amplitude),
t_0=t0, t_stop=tstop)
else:
Expand All @@ -1180,6 +1187,7 @@ def add_tonic_bias(self, *, cell_type=None, amplitude, t0=0, tstop=None):

for _cell_type, _amplitude in amplitude.items():
_add_cell_type_bias(network=self, cell_type=_cell_type,
section=section, bias_name=bias_name,
amplitude=_amplitude,
t_0=t0, t_stop=tstop)

Expand Down Expand Up @@ -1648,7 +1656,7 @@ def __repr__(self):


def _add_cell_type_bias(network: Network, amplitude: Union[float, dict],
cell_type=None,
cell_type=None, section='soma', bias_name='tonic',
t_0=0, t_stop=None):

if network is None:
Expand All @@ -1665,15 +1673,27 @@ def _add_cell_type_bias(network: Network, amplitude: Union[float, dict],
f'{list(network.cell_types.keys())}. '
f'Got {cell_type}')

if 'tonic' not in network.external_biases:
network.external_biases['tonic'] = dict()
if bias_name not in network.external_biases:
network.external_biases[bias_name] = dict()

if cell_type in network.external_biases['tonic']:
raise ValueError(f'Tonic bias already defined for {cell_type}')
if cell_type in network.external_biases[bias_name]:
raise ValueError(f'Bias named {bias_name} already defined '
f'for {cell_type}')

cell_type_bias = {
'amplitude': amplitude,
't0': t_0,
'tstop': t_stop
'tstop': t_stop,
'section': section
}
network.external_biases['tonic'][cell_type] = cell_type_bias

sections = list(network.cell_types[cell_type].sections.keys())

# error when section is defined that doesn't exist.
if section not in sections:
raise ValueError(f"section must be one of {sections}. "
f"Got {section}.")
else:
cell_type_bias['section'] = section

network.external_biases[bias_name][cell_type] = cell_type_bias
8 changes: 4 additions & 4 deletions hnn_core/network_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -441,10 +441,10 @@ def _create_cells_and_drives(self, threshold, record_vsec=False,
else:
cell.build()
# add tonic biases
if ('tonic' in self.net.external_biases and
src_type in self.net.external_biases['tonic']):
cell.create_tonic_bias(**self.net.external_biases
['tonic'][src_type])
for bias in self.net.external_biases:
if src_type in self.net.external_biases[bias]:
cell.create_tonic_bias(**self.net.external_biases
[bias][src_type])
cell.record(record_vsec, record_isec, record_ca)

# this call could belong in init of a _Cell (with threshold)?
Expand Down
12 changes: 8 additions & 4 deletions hnn_core/tests/assets/jones2009_3x3_drives.json
Original file line number Diff line number Diff line change
Expand Up @@ -2128,22 +2128,26 @@
"L2_pyramidal": {
"amplitude": 1.0,
"t0": 0,
"tstop": null
"tstop": null,
"section": "soma"
},
"L5_pyramidal": {
"amplitude": 0.0,
"t0": 0,
"tstop": null
"tstop": null,
"section": "soma"
},
"L2_basket": {
"amplitude": 0.0,
"t0": 0,
"tstop": null
"tstop": null,
"section": "soma"
},
"L5_basket": {
"amplitude": 0.0,
"t0": 0,
"tstop": null
"tstop": null,
"section": "soma"
}
}
},
Expand Down
15 changes: 14 additions & 1 deletion hnn_core/tests/test_network.py
Original file line number Diff line number Diff line change
Expand Up @@ -855,9 +855,22 @@ def test_tonic_biases():
assert 'tonic' in net.external_biases
assert 'L5_pyramidal' not in net.external_biases['tonic']
assert net.external_biases['tonic']['L2_pyramidal']['t0'] == 0
with pytest.raises(ValueError, match=r'Tonic bias already defined for.*$'):
with pytest.raises(ValueError, match=r'Bias named tonic already defined '
r'for.*$'):
net.add_tonic_bias(amplitude=tonic_bias_2)

net = jones_2009_model()
net.add_tonic_bias(amplitude=tonic_bias_2, bias_name='tonic_2', t0=100)
assert 'tonic_2' in net.external_biases
assert net.external_biases['tonic_2']['L2_pyramidal']['t0'] == 100

# non-existent section
net.external_biases = dict()

with pytest.raises(ValueError, match=(r'section must be one of .*'
' Got apical_4.')):
net.add_tonic_bias(amplitude={'L2_pyramidal': .5}, section='apical_4')


def test_network_mesh():
"""Test mesh for defining cell positions biases."""
Expand Down

0 comments on commit 2a82933

Please sign in to comment.