diff --git a/examples/plot_simulate_gamma.py b/examples/plot_simulate_gamma.py index b969be9446..db755d4877 100644 --- a/examples/plot_simulate_gamma.py +++ b/examples/plot_simulate_gamma.py @@ -82,7 +82,7 @@ dpls[trial_idx].plot_tfr_morlet(freqs, n_cycles=7, tmin=tmin, ax=axes[1]) ############################################################################### -# As a final exercise, let us try to re-run the simulation with a tonic bias +# Now, let us try to re-run the simulation with a tonic bias # applied to the L5 Pyramidal cells. Notice that the oscillation waveform is # more regular, with less noise due to the fact that the tonic depolarization # dominates over the influence of the Poisson drive. By default, a tonic bias @@ -108,6 +108,21 @@ from hnn_core.viz import plot_psd plot_psd(dpls[trial_idx], fmin=20., fmax=100., tmin=tmin) +############################################################################### +# Finally, we demonstrate the mechanistic link between PING and the GABAA decay +# time constant (`tau2`). Using the same network/drive configuration as before, +# we decrease `tau2` from 5 to 2 ms. This will shorten the effective +# refactory period between L5 pyramidal cell spikes and increase the PING +# frequency from ~50 to ~65 Hz. +net.cell_properties['L5_pyramidal']['synapses']['gabaa']['tau2'] = 2 +dpls = simulate_dipole(net, n_trials=1) + +fig, axes = plt.subplots(3, 1, sharex=True, figsize=(6, 6), + constrained_layout=True) +dpls[trial_idx].plot(ax=axes[0], show=False) +net.cell_response.plot_spikes_raster(ax=axes[1], show=False) +dpls[trial_idx].plot_tfr_morlet(freqs, n_cycles=7, tmin=tmin, ax=axes[2]) + ############################################################################### # References # ---------- diff --git a/hnn_core/cell.py b/hnn_core/cell.py index 79ea1a46e5..ced3c6000c 100644 --- a/hnn_core/cell.py +++ b/hnn_core/cell.py @@ -160,6 +160,7 @@ def gid(self, gid): def _set_biophysics(self, p_secs): "Set the biophysics for the cell." + from .cells_default import _set_variable_mech # neuron syntax is used to set values for mechanisms # sec.gbar_mech = x sets value of gbar for mech to x for all segs # in a section. This method is significantly faster than using @@ -177,10 +178,11 @@ def _set_biophysics(self, p_secs): for mech_name, p_mech in p_sec['mechs'].items(): sec.insert(mech_name) for attr, val in p_mech.items(): - if hasattr(val, '__call__'): + if val == 'variable': sec.push() for seg in sec: - setattr(seg, attr, val(h.distance(seg.x))) + val = _set_variable_mech(h.distance(seg.x)) + setattr(seg, attr, val) h.pop_section() else: setattr(sec, attr, val) diff --git a/hnn_core/cells_default.py b/hnn_core/cells_default.py index fd2107a6ca..c5e502b0ac 100644 --- a/hnn_core/cells_default.py +++ b/hnn_core/cells_default.py @@ -146,6 +146,11 @@ def _get_mechanisms(p_all, cell_type, section_names, mechanisms): return mech_props +def _set_variable_mech(x): + # this is a temporary hack + return 1e-6 * np.exp(3e-3 * x) + + def basket(cell_name='L2Basket', gid=None): """Get layer 2 / layer 5 basket cells. @@ -251,7 +256,7 @@ def pyramidal(cell_name, override_params=None, gid=None): syns = list(p_syn.keys()) if cell_name == 'L5Pyr': p_secs[key]['mechs'][ - 'ar']['gbar_ar'] = lambda x: 1e-6 * np.exp(3e-3 * x) + 'ar']['gbar_ar'] = 'variable' p_secs[key]['syns'] = syns for sec_name in p_secs: diff --git a/hnn_core/network.py b/hnn_core/network.py index 9494234bec..62ad61186b 100644 --- a/hnn_core/network.py +++ b/hnn_core/network.py @@ -230,20 +230,22 @@ def copy(self): return net_copy def _set_cell_properties(self): - '''Populate the network with cell objects''' - - for cell_type in self.pos_dict.keys(): - if cell_type in self.cellname_list: - if cell_type in ('L2_pyramidal', 'L5_pyramidal'): - p_secs, p_syn, topology, sect_loc = pyramidal( - cell_name=_short_name(cell_type)) - else: - p_secs, p_syn, topology, sect_loc = basket( - cell_name=_short_name(cell_type)) - self.cell_properties[cell_type] = {'sections': p_secs, - 'synapses': p_syn, - 'topology': topology, - 'sect_loc': sect_loc} + '''Set cell properties by cell type + + This relies on self.cellname_list and must be updated when introducting + new cell types to HNN. + ''' + for cell_type in self.cellname_list: + if cell_type in ('L2_pyramidal', 'L5_pyramidal'): + p_secs, p_syn, topology, sect_loc = pyramidal( + cell_name=_short_name(cell_type)) + else: + p_secs, p_syn, topology, sect_loc = basket( + cell_name=_short_name(cell_type)) + self.cell_properties[cell_type] = {'sections': p_secs, + 'synapses': p_syn, + 'topology': topology, + 'sect_loc': sect_loc} def add_evoked_drive(self, name, *, mu, sigma, numspikes, sync_within_trial=False, location, diff --git a/hnn_core/network_builder.py b/hnn_core/network_builder.py index e3ccd42411..cb7d74b388 100644 --- a/hnn_core/network_builder.py +++ b/hnn_core/network_builder.py @@ -13,7 +13,6 @@ h.nrnunit_use_legacy(1) from .cell import Cell, _ArtificialCell -from .cells_default import pyramidal, basket from .params import _long_name, _short_name from copy import deepcopy diff --git a/hnn_core/tests/test_cell.py b/hnn_core/tests/test_cell.py index 02a5674eb2..123aeaed4c 100644 --- a/hnn_core/tests/test_cell.py +++ b/hnn_core/tests/test_cell.py @@ -61,7 +61,7 @@ def test_cell(): 'gbar_km': 60 }, 'ca': { - 'gbar_ca': lambda x: 3e-3 * x + 'gbar_ca': 'variable' } } }