From adffb779b26b0b8f67d7d23f434ea89e422f6380 Mon Sep 17 00:00:00 2001 From: Nicholas Tolley Date: Wed, 25 Oct 2023 13:03:08 -0400 Subject: [PATCH 1/9] First pass at adding dipoles for individual cells --- hnn_core/cell_response.py | 12 +++++++++++ hnn_core/dipole.py | 8 ++++++- hnn_core/network_builder.py | 12 +++++++++++ hnn_core/parallel_backends.py | 1 + hnn_core/tests/test_dipole.py | 39 +++++++++++++++++++++++++++++++---- 5 files changed, 67 insertions(+), 5 deletions(-) diff --git a/hnn_core/cell_response.py b/hnn_core/cell_response.py index e36fe3b36..cd1500549 100644 --- a/hnn_core/cell_response.py +++ b/hnn_core/cell_response.py @@ -56,6 +56,9 @@ class CellResponse(object): isec : list (n_trials,) of dict, shape Each element of the outer list is a trial. Dictionary indexed by gids containing currents for cell sections. + dcell : list (n_trials,) of dict, shape + Each element of the outer list is a trial. + Dictionary indexed by gids containing dipoles for individual cells. times : array-like, shape (n_times,) Array of time points for samples in continuous data. This includes vsoma and isoma. @@ -115,6 +118,7 @@ def __init__(self, spike_times=None, spike_gids=None, spike_types=None, self._spike_types = spike_types self._vsec = list() self._isec = list() + self._dcell = list() if times is not None: if not isinstance(times, (list, np.ndarray)): raise TypeError("'times' is an np.ndarray of simulation times") @@ -225,6 +229,10 @@ def vsec(self): @property def isec(self): return self._isec + + @property + def dcell(self): + return self._dcell @property def times(self): @@ -423,6 +431,10 @@ def to_dict(self): # Turn `int` gid keys into string values for hdf5 format trial = dict((str(key), val) for key, val in trial.items()) cell_response_data['isec'].append(trial) + for trial in self.dcell: + # Turn `int` gid keys into string values for hdf5 format + trial = dict((str(key), val) for key, val in trial.items()) + cell_response_data['dcell'].append(trial) cell_response_data['times'] = self.times return cell_response_data diff --git a/hnn_core/dipole.py b/hnn_core/dipole.py index 28fe515a4..8e2abf3f6 100644 --- a/hnn_core/dipole.py +++ b/hnn_core/dipole.py @@ -16,7 +16,7 @@ def simulate_dipole(net, tstop, dt=0.025, n_trials=None, record_vsec=False, - record_isec=False, postproc=False): + record_isec=False, record_dcell=False, postproc=False): """Simulate a dipole given the experiment parameters. Parameters @@ -37,6 +37,8 @@ def simulate_dipole(net, tstop, dt=0.025, n_trials=None, record_vsec=False, record_isec : 'all' | 'soma' | False Option to record voltages from all sections ('all'), or just the soma ('soma'). Default: False. + record_dcell : bool + Option to record dipole from individual cells. Default: False. postproc : bool If True, smoothing (``dipole_smooth_win``) and scaling (``dipole_scalefctr``) values are read from the parameter file, and @@ -96,6 +98,10 @@ def simulate_dipole(net, tstop, dt=0.025, n_trials=None, record_vsec=False, net._params['record_isec'] = record_isec + _check_option('record_dcell', record_dcell, [True, False]) + + net._params['record_dcell'] = record_dcell + if postproc: warnings.warn('The postproc-argument is deprecated and will be removed' ' in a future release of hnn-core. Please define ' diff --git a/hnn_core/network_builder.py b/hnn_core/network_builder.py index 0d7c33f46..438f68f8a 100644 --- a/hnn_core/network_builder.py +++ b/hnn_core/network_builder.py @@ -99,6 +99,10 @@ def simulation_time(): for sec_name, isec in isec_dict.items(): isec_py[gid][sec_name] = { key: isec.to_python() for key, isec in isec.items()} + + dcell_py = dict() + for gid, dcell in neuron_net._dcell.items(): + dcell_py[gid] = dcell.to_python() dpl_data = np.c_[ neuron_net._nrn_dipoles['L2_pyramidal'].as_numpy() + @@ -119,6 +123,7 @@ def simulation_time(): 'gid_ranges': net.gid_ranges, 'vsec': vsec_py, 'isec': isec_py, + 'dcell': dcell_py, 'rec_data': rec_arr_py, 'rec_times': rec_times_py, 'times': times.to_python()} @@ -291,6 +296,7 @@ def __init__(self, net, trial_idx=0): self._vsec = dict() self._isec = dict() + self._dcell = dict() self._nrn_rec_arrays = dict() self._nrn_rec_callbacks = list() @@ -562,6 +568,9 @@ def aggregate_data(self, n_samples): nrn_dpl = self._nrn_dipoles[_long_name(cell.name)] nrn_dpl.add(cell.dipole) + if self.net._params['record_dcell']: + self._dcell[cell.gid] = cell.dipole + self._vsec[cell.gid] = cell.vsec self._isec[cell.gid] = cell.isec @@ -574,6 +583,7 @@ def aggregate_data(self, n_samples): # aggregate the currents and voltages independently on each proc vsec_list = _PC.py_gather(self._vsec, 0) isec_list = _PC.py_gather(self._isec, 0) + dcell_list = _PC.py_gather(self._dcell, 0) # combine spiking data from each proc spike_times_list = _PC.py_gather(self._spike_times, 0) @@ -589,6 +599,8 @@ def aggregate_data(self, n_samples): self._vsec.update(vsec) for isec in isec_list: self._isec.update(isec) + for dcell in dcell_list: + self._dcell.update(dcell) _PC.barrier() # get all nodes to this place before continuing diff --git a/hnn_core/parallel_backends.py b/hnn_core/parallel_backends.py index b022e5965..c2d311e6a 100644 --- a/hnn_core/parallel_backends.py +++ b/hnn_core/parallel_backends.py @@ -53,6 +53,7 @@ def _gather_trial_data(sim_data, net, n_trials, postproc): net.cell_response.update_types(net.gid_ranges) net.cell_response._vsec.append(sim_data[idx]['vsec']) net.cell_response._isec.append(sim_data[idx]['isec']) + net.cell_response._dcell.append(sim_data[idx]['dcell']) # extracellular array for arr_name, arr in net.rec_arrays.items(): diff --git a/hnn_core/tests/test_dipole.py b/hnn_core/tests/test_dipole.py index 22af87b3c..fd763f1f3 100644 --- a/hnn_core/tests/test_dipole.py +++ b/hnn_core/tests/test_dipole.py @@ -187,6 +187,8 @@ def test_dipole_simulation(): with pytest.raises(ValueError, match="Invalid value for the"): simulate_dipole(net, tstop=25., n_trials=1, record_vsec=False, record_isec='abc') + with pytest.raises(ValueError, match="Invalid value for the"): + simulate_dipole(net, tstop=25., n_trials=1, record_dcell='abc') # test Network.copy() returns 'bare' network after simulating dpl = simulate_dipole(net, tstop=25., n_trials=1)[0] @@ -213,32 +215,39 @@ def test_cell_response_backends(run_hnn_core_fixture): # reduced simulation has n_trials=2 trial_idx, n_trials, gid = 0, 2, 7 - _, joblib_net = run_hnn_core_fixture(backend='joblib', n_jobs=1, + joblib_dpl, joblib_net = run_hnn_core_fixture(backend='joblib', n_jobs=1, reduced=True, record_vsec='all', - record_isec='soma') - _, mpi_net = run_hnn_core_fixture(backend='mpi', n_procs=2, reduced=True, - record_vsec='all', record_isec='soma') + record_isec='soma', record_dcell=True) + mpi_dpl, mpi_net = run_hnn_core_fixture(backend='mpi', n_procs=2, reduced=True, + record_vsec='all', record_isec='soma', + record_dcell=True) n_times = len(joblib_net.cell_response.times) assert len(joblib_net.cell_response.vsec) == n_trials assert len(joblib_net.cell_response.isec) == n_trials + assert len(joblib_net.cell_response.dcell) == n_trials assert len(joblib_net.cell_response.vsec[trial_idx][gid]) == 8 # num sec assert len(joblib_net.cell_response.isec[trial_idx][gid]) == 1 assert len(joblib_net.cell_response.vsec[ trial_idx][gid]['apical_1']) == n_times assert len(joblib_net.cell_response.isec[ trial_idx][gid]['soma']['soma_gabaa']) == n_times + assert len(joblib_net.cell_response.isec[trial_idx][gid]) == n_times + assert len(mpi_net.cell_response.vsec) == n_trials assert len(mpi_net.cell_response.isec) == n_trials + assert len(mpi_net.cell_response.dcell) == n_trials assert len(mpi_net.cell_response.vsec[trial_idx][gid]) == 8 # num sec assert len(mpi_net.cell_response.isec[trial_idx][gid]) == 1 assert len(mpi_net.cell_response.vsec[ trial_idx][gid]['apical_1']) == n_times assert len(mpi_net.cell_response.isec[ trial_idx][gid]['soma']['soma_gabaa']) == n_times + assert len(mpi_net.cell_response.isec[trial_idx][gid]) == n_times assert mpi_net.cell_response.vsec == joblib_net.cell_response.vsec assert mpi_net.cell_response.isec == joblib_net.cell_response.isec + assert mpi_net.cell_response.dcell == joblib_net.cell_response.dcell # Test if spike time falls within depolarization window above v_thresh v_thresh = 0.0 @@ -259,6 +268,28 @@ def test_cell_response_backends(run_hnn_core_fixture): g == gid_ran[idx_drive]] assert_allclose(np.array(event_times), np.array(net_ets)) + # test that individual cell dipoles match aggregate dipole + L5_dipole = np.array([joblib_net.cell_response.dcell[0][gid] for + gid in list(joblib_net.gid_ranges['L5_pyramidal'])]) + L2_dipole = np.array([joblib_net.cell_response.dcell[0][gid] + for gid in list(joblib_net.gid_ranges['L2_pyramidal'])]) + agg_dipole = np.concatenate([L2_dipole, L5_dipole], axis=0) + + L5_dipole_sum = np.sum(L5_dipole, axis=0) + L2_dipole_sum = np.sum(L2_dipole, axis=0) + agg_dipole_sum = np.sum(agg_dipole, axis=0) + + dipole_data = np.stack([agg_dipole_sum, L2_dipole_sum, L5_dipole_sum], axis=1) + + test_dpl = Dipole(dpl[0].times, dipole_data) + N_pyr_x = joblib_net._params['N_pyr_x'] + N_pyr_y = joblib_net._params['N_pyr_y'] + test_dpl._baseline_renormalize(N_pyr_x, N_pyr_y) + test_dpl._convert_fAm_to_nAm() + + assert np.all(test_dpl.data['agg'] == joblib_dpl[0].data['agg']) + assert np.all(test_dpl.data['agg'] == mpi_dpl[0].data['agg']) + def test_rmse(): """Test to check RMSE calculation""" From 0b120fc930ac3a614a23250de649655b7a60efc4 Mon Sep 17 00:00:00 2001 From: Nicholas Tolley Date: Wed, 25 Oct 2023 13:10:12 -0400 Subject: [PATCH 2/9] Flake8 --- hnn_core/tests/test_dipole.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hnn_core/tests/test_dipole.py b/hnn_core/tests/test_dipole.py index fd763f1f3..f16cb262b 100644 --- a/hnn_core/tests/test_dipole.py +++ b/hnn_core/tests/test_dipole.py @@ -281,7 +281,7 @@ def test_cell_response_backends(run_hnn_core_fixture): dipole_data = np.stack([agg_dipole_sum, L2_dipole_sum, L5_dipole_sum], axis=1) - test_dpl = Dipole(dpl[0].times, dipole_data) + test_dpl = Dipole(joblib_dpl[0].times, dipole_data) N_pyr_x = joblib_net._params['N_pyr_x'] N_pyr_y = joblib_net._params['N_pyr_y'] test_dpl._baseline_renormalize(N_pyr_x, N_pyr_y) From 4345cad7c27ae31d2ada821ab6d44ac1e07fcc9c Mon Sep 17 00:00:00 2001 From: Nicholas Tolley Date: Wed, 25 Oct 2023 13:25:44 -0400 Subject: [PATCH 3/9] Flake8 for real --- hnn_core/tests/test_dipole.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/hnn_core/tests/test_dipole.py b/hnn_core/tests/test_dipole.py index f16cb262b..8a3c98059 100644 --- a/hnn_core/tests/test_dipole.py +++ b/hnn_core/tests/test_dipole.py @@ -215,12 +215,12 @@ def test_cell_response_backends(run_hnn_core_fixture): # reduced simulation has n_trials=2 trial_idx, n_trials, gid = 0, 2, 7 - joblib_dpl, joblib_net = run_hnn_core_fixture(backend='joblib', n_jobs=1, - reduced=True, record_vsec='all', - record_isec='soma', record_dcell=True) - mpi_dpl, mpi_net = run_hnn_core_fixture(backend='mpi', n_procs=2, reduced=True, - record_vsec='all', record_isec='soma', - record_dcell=True) + joblib_dpl, joblib_net = run_hnn_core_fixture( + backend='joblib', n_jobs=1, reduced=True, record_vsec='all', + record_isec='soma', record_dcell=True) + mpi_dpl, mpi_net = run_hnn_core_fixture( + backend='mpi', n_procs=2, reduced=True, record_vsec='all', + record_isec='soma', record_dcell=True) n_times = len(joblib_net.cell_response.times) assert len(joblib_net.cell_response.vsec) == n_trials @@ -233,7 +233,6 @@ def test_cell_response_backends(run_hnn_core_fixture): assert len(joblib_net.cell_response.isec[ trial_idx][gid]['soma']['soma_gabaa']) == n_times assert len(joblib_net.cell_response.isec[trial_idx][gid]) == n_times - assert len(mpi_net.cell_response.vsec) == n_trials assert len(mpi_net.cell_response.isec) == n_trials @@ -279,7 +278,8 @@ def test_cell_response_backends(run_hnn_core_fixture): L2_dipole_sum = np.sum(L2_dipole, axis=0) agg_dipole_sum = np.sum(agg_dipole, axis=0) - dipole_data = np.stack([agg_dipole_sum, L2_dipole_sum, L5_dipole_sum], axis=1) + dipole_data = np.stack( + [agg_dipole_sum, L2_dipole_sum, L5_dipole_sum], axis=1) test_dpl = Dipole(joblib_dpl[0].times, dipole_data) N_pyr_x = joblib_net._params['N_pyr_x'] From 276e80240ed5c9a6b35b2fb6b8fad17c25ae0e3c Mon Sep 17 00:00:00 2001 From: Nicholas Tolley Date: Wed, 25 Oct 2023 13:34:56 -0400 Subject: [PATCH 4/9] yet another flake8 :( --- hnn_core/tests/test_dipole.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hnn_core/tests/test_dipole.py b/hnn_core/tests/test_dipole.py index 8a3c98059..0932700bf 100644 --- a/hnn_core/tests/test_dipole.py +++ b/hnn_core/tests/test_dipole.py @@ -270,8 +270,8 @@ def test_cell_response_backends(run_hnn_core_fixture): # test that individual cell dipoles match aggregate dipole L5_dipole = np.array([joblib_net.cell_response.dcell[0][gid] for gid in list(joblib_net.gid_ranges['L5_pyramidal'])]) - L2_dipole = np.array([joblib_net.cell_response.dcell[0][gid] - for gid in list(joblib_net.gid_ranges['L2_pyramidal'])]) + L2_dipole = np.array([joblib_net.cell_response.dcell[0][gid] for + gid in list(joblib_net.gid_ranges['L2_pyramidal'])]) agg_dipole = np.concatenate([L2_dipole, L5_dipole], axis=0) L5_dipole_sum = np.sum(L5_dipole, axis=0) From da91881d5dca06b2f1cb6d5dc62bdf6eae07f7c9 Mon Sep 17 00:00:00 2001 From: Nicholas Tolley Date: Wed, 25 Oct 2023 13:40:43 -0400 Subject: [PATCH 5/9] ... --- hnn_core/cell_response.py | 2 +- hnn_core/network_builder.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hnn_core/cell_response.py b/hnn_core/cell_response.py index cd1500549..075bd1b0f 100644 --- a/hnn_core/cell_response.py +++ b/hnn_core/cell_response.py @@ -229,7 +229,7 @@ def vsec(self): @property def isec(self): return self._isec - + @property def dcell(self): return self._dcell diff --git a/hnn_core/network_builder.py b/hnn_core/network_builder.py index 438f68f8a..e78e091c1 100644 --- a/hnn_core/network_builder.py +++ b/hnn_core/network_builder.py @@ -99,7 +99,7 @@ def simulation_time(): for sec_name, isec in isec_dict.items(): isec_py[gid][sec_name] = { key: isec.to_python() for key, isec in isec.items()} - + dcell_py = dict() for gid, dcell in neuron_net._dcell.items(): dcell_py[gid] = dcell.to_python() From 05ab75dd2c23ceae95ce34410bf947ade54d0df1 Mon Sep 17 00:00:00 2001 From: Nicholas Tolley Date: Wed, 25 Oct 2023 14:31:32 -0400 Subject: [PATCH 6/9] fix key errors --- hnn_core/params_default.py | 1 + hnn_core/tests/test_cell_response.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/hnn_core/params_default.py b/hnn_core/params_default.py index 502f92f4c..dde86cf88 100644 --- a/hnn_core/params_default.py +++ b/hnn_core/params_default.py @@ -149,6 +149,7 @@ def get_params_default(nprox=2, ndist=1): 'record_isoma': 0, # whether to record somatic currents 'record_vsec': 0, # whether to record voltages 'record_isec': 0, # whether to record currents + 'record_dcell': 0, # whether to record cell dipoles # numerics # N_trials of 1 means that seed is set by rank diff --git a/hnn_core/tests/test_cell_response.py b/hnn_core/tests/test_cell_response.py index ce0373db1..802b4b1c6 100644 --- a/hnn_core/tests/test_cell_response.py +++ b/hnn_core/tests/test_cell_response.py @@ -43,7 +43,7 @@ def test_cell_response(tmp_path): # reset clears all recorded variables, but leaves simulation time intact assert len(cell_response.times) == len(sim_times) sim_attributes = ['_spike_times', '_spike_gids', '_spike_types', - '_vsec', '_isec'] + '_vsec', '_isec', '_dcell'] net_attributes = ['_times', '_cell_type_names'] # `Network.__init__` # creates these check that we always know which response attributes are # simulated see #291 for discussion; objective is to keep cell_response From 95ff6cef7b34bc339d7d3f9cf80873311996d5bf Mon Sep 17 00:00:00 2001 From: Nicholas Tolley Date: Wed, 25 Oct 2023 14:48:24 -0400 Subject: [PATCH 7/9] add dsec to conftest --- hnn_core/tests/conftest.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/hnn_core/tests/conftest.py b/hnn_core/tests/conftest.py index 643f8697e..87906c038 100644 --- a/hnn_core/tests/conftest.py +++ b/hnn_core/tests/conftest.py @@ -75,8 +75,8 @@ def pytest_runtest_setup(item): def run_hnn_core_fixture(): def _run_hnn_core_fixture(backend=None, n_procs=None, n_jobs=1, reduced=False, record_vsec=False, - record_isec=False, postproc=False, - electrode_array=None): + record_isec=False, record_dcell=False, + postproc=False, electrode_array=None): hnn_core_root = op.dirname(hnn_core.__file__) # default params @@ -105,15 +105,18 @@ def _run_hnn_core_fixture(backend=None, n_procs=None, n_jobs=1, with MPIBackend(n_procs=n_procs, mpi_cmd='mpiexec'): dpls = simulate_dipole(net, record_vsec=record_vsec, record_isec=record_isec, + record_dcell=record_dcell, postproc=postproc, tstop=tstop) elif backend == 'joblib': with JoblibBackend(n_jobs=n_jobs): dpls = simulate_dipole(net, record_vsec=record_vsec, record_isec=record_isec, + record_dcell=record_dcell, postproc=postproc, tstop=tstop) else: dpls = simulate_dipole(net, record_vsec=record_vsec, record_isec=record_isec, + record_dcell=record_dcell, postproc=postproc, tstop=tstop) # check that the network object is picklable after the simulation From 2de40b636f73256505aae2e0161f2049b7307267 Mon Sep 17 00:00:00 2001 From: Nicholas Tolley Date: Wed, 25 Oct 2023 15:35:06 -0400 Subject: [PATCH 8/9] Test typo --- hnn_core/tests/test_dipole.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hnn_core/tests/test_dipole.py b/hnn_core/tests/test_dipole.py index 0932700bf..47941d68c 100644 --- a/hnn_core/tests/test_dipole.py +++ b/hnn_core/tests/test_dipole.py @@ -232,7 +232,7 @@ def test_cell_response_backends(run_hnn_core_fixture): trial_idx][gid]['apical_1']) == n_times assert len(joblib_net.cell_response.isec[ trial_idx][gid]['soma']['soma_gabaa']) == n_times - assert len(joblib_net.cell_response.isec[trial_idx][gid]) == n_times + assert len(joblib_net.cell_response.dcell[trial_idx][gid]) == n_times assert len(mpi_net.cell_response.vsec) == n_trials assert len(mpi_net.cell_response.isec) == n_trials @@ -243,7 +243,7 @@ def test_cell_response_backends(run_hnn_core_fixture): trial_idx][gid]['apical_1']) == n_times assert len(mpi_net.cell_response.isec[ trial_idx][gid]['soma']['soma_gabaa']) == n_times - assert len(mpi_net.cell_response.isec[trial_idx][gid]) == n_times + assert len(mpi_net.cell_response.dcell[trial_idx][gid]) == n_times assert mpi_net.cell_response.vsec == joblib_net.cell_response.vsec assert mpi_net.cell_response.isec == joblib_net.cell_response.isec assert mpi_net.cell_response.dcell == joblib_net.cell_response.dcell From 39dc47bc123df8689345713becab245e3b532733 Mon Sep 17 00:00:00 2001 From: Nicholas Tolley Date: Mon, 8 Jan 2024 17:16:28 -0500 Subject: [PATCH 9/9] Add GABA weights to drives --- hnn_core/drives.py | 15 ++++++++++++-- hnn_core/network.py | 50 +++++++++++++++++++++++++++++++++++++-------- 2 files changed, 55 insertions(+), 10 deletions(-) diff --git a/hnn_core/drives.py b/hnn_core/drives.py index 834f31a41..f15a61808 100644 --- a/hnn_core/drives.py +++ b/hnn_core/drives.py @@ -10,7 +10,8 @@ _extract_drive_specs_from_hnn_params) -def _get_target_properties(weights_ampa, weights_nmda, synaptic_delays, +def _get_target_properties(weights_ampa, weights_nmda, weights_gabaa, + weights_gababb, synaptic_delays, location, probability=1.0): """Retrieve drive properties associated with each target cell type @@ -23,13 +24,23 @@ def _get_target_properties(weights_ampa, weights_nmda, synaptic_delays, weights_ampa = dict() if weights_nmda is None: weights_nmda = dict() + if weights_gabaa is None: + weights_gabaa = dict() + if weights_gababb is None: + weights_gababb = dict() weights_by_type = {cell_type: dict() for cell_type in - (set(weights_ampa.keys()) | set(weights_nmda.keys()))} + (set(weights_ampa.keys()) | set(weights_nmda.keys()) | + set(weights_gabaa.keys()) | + set(weights_gababb.keys()))} for cell_type in weights_ampa: weights_by_type[cell_type].update({'ampa': weights_ampa[cell_type]}) for cell_type in weights_nmda: weights_by_type[cell_type].update({'nmda': weights_nmda[cell_type]}) + for cell_type in weights_gabaa: + weights_by_type[cell_type].update({'gabaa': weights_gabaa[cell_type]}) + for cell_type in weights_gababb: + weights_by_type[cell_type].update({'gabab': weights_gababb[cell_type]}) target_populations = set(weights_by_type) if not target_populations: diff --git a/hnn_core/network.py b/hnn_core/network.py index 8aa754de1..629072caa 100644 --- a/hnn_core/network.py +++ b/hnn_core/network.py @@ -485,6 +485,7 @@ def copy(self): def add_evoked_drive(self, name, *, mu, sigma, numspikes, location, n_drive_cells='n_cells', cell_specific=True, weights_ampa=None, weights_nmda=None, + weights_gabaa=None, weights_gabab=None, space_constant=3., synaptic_delays=0.1, probability=1.0, event_seed=2, conn_seed=3): """Add an 'evoked' external drive to the network @@ -528,6 +529,12 @@ def add_evoked_drive(self, name, *, mu, sigma, numspikes, location, weights_nmda : dict or None Synaptic weights (in uS) of NMDA receptors on each targeted cell type (dict keys). Cell types omitted from the dict are set to zero. + weights_gabaa : dict or None + Synaptic weights (in uS) of GABAa receptors on each targeted cell + type (dict keys). Cell types omitted from the dict are set to zero. + weights_gabab : dict or None + Synaptic weights (in uS) of GABAb receptors on each targeted cell + type (dict keys). Cell types omitted from the dict are set to zero. synaptic_delays : dict or float Synaptic delay (in ms) at the column origin, dispersed laterally as a function of the space_constant. If float, applies to all target @@ -580,14 +587,16 @@ def add_evoked_drive(self, name, *, mu, sigma, numspikes, location, drive['dynamics'] = dict(mu=mu, sigma=sigma, numspikes=numspikes) drive['events'] = list() - self._attach_drive(name, drive, weights_ampa, weights_nmda, location, + self._attach_drive(name, drive, weights_ampa, weights_nmda, + weights_gabaa, weights_gabab, location, space_constant, synaptic_delays, n_drive_cells, cell_specific, probability) def add_poisson_drive(self, name, *, tstart=0, tstop=None, rate_constant, location, n_drive_cells='n_cells', cell_specific=True, weights_ampa=None, - weights_nmda=None, space_constant=100., + weights_nmda=None, weights_gabaa=None, + weights_gabab=None, space_constant=100., synaptic_delays=0.1, probability=1.0, event_seed=2, conn_seed=3): """Add a Poisson-distributed external drive to the network @@ -635,6 +644,12 @@ def add_poisson_drive(self, name, *, tstart=0, tstop=None, rate_constant, weights_nmda : dict or None Synaptic weights (in uS) of NMDA receptors on each targeted cell type (dict keys). Cell types omitted from the dict are set to zero. + weights_gabaa : dict or None + Synaptic weights (in uS) of GABAa receptors on each targeted cell + type (dict keys). Cell types omitted from the dict are set to zero. + weights_gabab : dict or None + Synaptic weights (in uS) of GABAb receptors on each targeted cell + type (dict keys). Cell types omitted from the dict are set to zero. synaptic_delays : dict or float Synaptic delay (in ms) at the column origin, dispersed laterally as a function of the space_constant. If float, applies to all target @@ -664,6 +679,8 @@ def add_poisson_drive(self, name, *, tstart=0, tstop=None, rate_constant, tstop=tstop) target_populations = _get_target_properties(weights_ampa, weights_nmda, + weights_gabaa, + weights_gabab, synaptic_delays, location)[0] _check_poisson_rates(rate_constant, target_populations, @@ -689,7 +706,8 @@ def add_poisson_drive(self, name, *, tstart=0, tstop=None, rate_constant, rate_constant=rate_constant) drive['events'] = list() - self._attach_drive(name, drive, weights_ampa, weights_nmda, location, + self._attach_drive(name, drive, weights_ampa, weights_nmda, + weights_gabaa, weights_gabab, location, space_constant, synaptic_delays, n_drive_cells, cell_specific, probability) @@ -697,6 +715,7 @@ def add_bursty_drive(self, name, *, tstart=0, tstart_std=0, tstop=None, location, burst_rate, burst_std=0, numspikes=2, spike_isi=10, n_drive_cells=1, cell_specific=False, weights_ampa=None, weights_nmda=None, + weights_gabaa=None, weights_gabab=None, synaptic_delays=0.1, space_constant=100., probability=1.0, event_seed=2, conn_seed=3): """Add a bursty (rhythmic) external drive to all cells of the network @@ -751,6 +770,12 @@ def add_bursty_drive(self, name, *, tstart=0, tstart_std=0, tstop=None, weights_nmda : dict or None Synaptic weights (in uS) of NMDA receptors on each targeted cell type (dict keys). Cell types omitted from the dict are set to zero. + weights_gabaa : dict or None + Synaptic weights (in uS) of GABAa receptors on each targeted cell + type (dict keys). Cell types omitted from the dict are set to zero. + weights_gabab : dict or None + Synaptic weights (in uS) of GABAb receptors on each targeted cell + type (dict keys). Cell types omitted from the dict are set to zero. synaptic_delays : dict or float Synaptic delay (in ms) at the column origin, dispersed laterally as a function of the space_constant. If float, applies to all target @@ -795,11 +820,13 @@ def add_bursty_drive(self, name, *, tstart=0, tstart_std=0, tstop=None, numspikes=numspikes, spike_isi=spike_isi) drive['events'] = list() - self._attach_drive(name, drive, weights_ampa, weights_nmda, location, + self._attach_drive(name, drive, weights_ampa, weights_nmda, + weights_gabaa, weights_gabab, location, space_constant, synaptic_delays, n_drive_cells, cell_specific, probability) - def _attach_drive(self, name, drive, weights_ampa, weights_nmda, location, + def _attach_drive(self, name, drive, weights_ampa, weights_nmda, + weights_gabaa, weights_gabab, location, space_constant, synaptic_delays, n_drive_cells, cell_specific, probability): """Attach a drive to network based on connectivity information @@ -816,6 +843,12 @@ def _attach_drive(self, name, drive, weights_ampa, weights_nmda, location, weights_nmda : dict or None Synaptic weights (in uS) of NMDA receptors on each targeted cell type (dict keys). Cell types omitted from the dict are set to zero. + weights_gabaa : dict or None + Synaptic weights (in uS) of GABAa receptors on each targeted cell + type (dict keys). Cell types omitted from the dict are set to zero. + weights_gabab : dict or None + Synaptic weights (in uS) of GABAb receptors on each targeted cell + type (dict keys). Cell types omitted from the dict are set to zero. location : str Target location of synapses. Must be an element of `Cell.sect_loc` such as 'proximal' or 'distal', which defines a @@ -866,7 +899,8 @@ def _attach_drive(self, name, drive, weights_ampa, weights_nmda, location, # allow passing weights as None, convert to dict here (target_populations, weights_by_type, delays_by_type, probability_by_type) = \ - _get_target_properties(weights_ampa, weights_nmda, synaptic_delays, + _get_target_properties(weights_ampa, weights_nmda, weights_gabaa, + weights_gabab, synaptic_delays, location, probability) # weights passed must correspond to cells in the network @@ -977,8 +1011,8 @@ def _attach_drive(self, name, drive, weights_ampa, weights_nmda, location, receptor=receptor, weight=weights, delay=delays, lamtha=space_constant, probability=probability, conn_seed=drive['conn_seed'] + seed_increment) - # Ensure that AMPA/NMDA connections target the same gids - # when probability < 1 + # Ensure that multireceptor connections target the + # same gids when probability < 1 if receptor_idx > 0: self.connectivity[-1]['src_gids'] = \ self.connectivity[-2]['src_gids']