From 543d94a95ec898be5a09c47960ee55b77b08df9c Mon Sep 17 00:00:00 2001 From: Nicholas Tolley Date: Mon, 23 Sep 2024 12:38:02 -0400 Subject: [PATCH 01/14] add tests and type checks for synaptic gains --- hnn_core/network.py | 53 ++++++++++++++++++++++++++++++++++ hnn_core/network_builder.py | 1 + hnn_core/tests/test_network.py | 39 +++++++++++++++++++++++++ 3 files changed, 93 insertions(+) diff --git a/hnn_core/network.py b/hnn_core/network.py index 3315c44d3..69de6d034 100644 --- a/hnn_core/network.py +++ b/hnn_core/network.py @@ -1358,6 +1358,8 @@ def add_connection(self, src_gids, target_gids, loc, receptor, _validate_type(item, (int, float), arg_name, 'int or float') conn['nc_dict'][key] = item + conn['nc_dict']['gain'] = 1.0 + # Probabilistically define connections if probability != 1.0: _connection_probability(conn, probability, conn_seed) @@ -1428,6 +1430,55 @@ def add_electrode_array(self, name, electrode_pos, *, conductivity=0.3, method=method, min_distance=min_distance)}) + def update_weights(self, e_e=1.0, e_i=1.0, i_e=1.0, i_i=1.0, copy=True): + """Update synaptic weights of the network. + + Parameters + ---------- + e_e : float + Synaptic gain of excitatory to excitatory connections (default 1.0) + e_i : float + Synaptic gain of excitatory to inhibitory connections (default 1.0) + i_e : float + Synaptic gain of inhibitory to excitatory connections (default 1.0) + i_i : float + Synaptic gain of inhibitory to inhibitory connections (default 1.0) + copy : bool + If True, create a copy of the network. If False, update the network + in place (default True) + """ + _validate_type(copy, bool, 'copy') + + net = self.copy() if copy else self + + e_conns = pick_connection(self, receptor=['ampa', 'nmda']) + e_cells = np.concatenate([list(net.connectivity[ + conn_idx]['src_gids']) for conn_idx in e_conns]).tolist() + + i_conns = pick_connection(self, receptor=['gabaa', 'gabab']) + i_cells = np.concatenate([list(net.connectivity[ + conn_idx]['src_gids']) for conn_idx in i_conns]).tolist() + conn_types = { + 'e_e': (e_e, e_cells, e_cells), + 'e_i': (e_i, e_cells, i_cells), + 'i_e': (i_e, i_cells, e_cells), + 'i_i': (i_i, i_cells, i_cells) + } + + for conn_type, (gain, e_vals, i_vals) in conn_types.items(): + _validate_type(gain, (int, float), conn_type, 'int or float') + if gain < 0.0: + raise ValueError("Synaptic gains must be non-negative." + f"Got {gain} for '{conn_type}'.") + + conn_indices = pick_connection(net, src_gids=e_vals, + target_gids=i_vals) + for conn_idx in conn_indices: + net.connectivity[conn_idx]['nc_dict']['gain'] = gain + + if copy: + return net + def plot_cells(self, ax=None, show=True): """Plot the cells using Network.pos_dict. @@ -1495,6 +1546,8 @@ class _Connectivity(dict): Synaptic delay in ms. lamtha : float Space constant. + gain : float + Multiplicative factor for synaptic weight. probability : float Probability of connection between any src-target pair. Defaults to 1.0 producing an all-to-all pattern. diff --git a/hnn_core/network_builder.py b/hnn_core/network_builder.py index 98f7ba1b8..230f20e06 100644 --- a/hnn_core/network_builder.py +++ b/hnn_core/network_builder.py @@ -477,6 +477,7 @@ def _connect_celltypes(self): for conn in connectivity: loc, receptor = conn['loc'], conn['receptor'] nc_dict = deepcopy(conn['nc_dict']) + nc_dict['A_weight'] *= nc_dict['gain'] # Gather indices of targets on current node valid_targets = set() for src_gid, target_gids in conn['gid_pairs'].items(): diff --git a/hnn_core/tests/test_network.py b/hnn_core/tests/test_network.py index 3a7af5946..f2f518975 100644 --- a/hnn_core/tests/test_network.py +++ b/hnn_core/tests/test_network.py @@ -895,6 +895,45 @@ def test_network_mesh(): _ = law_2021_model(mesh_shape=mesh_shape) +def test_synaptic_gains(): + """Test synaptic gains update""" + net = jones_2009_model() + e_cell_names = ['L2_pyramidal', 'L5_pyramidal'] + i_cell_names = ['L2_basket', 'L5_basket'] + + # Type check on gains + arg_names = ['e_e', 'e_i', 'i_e', 'i_i'] + for arg in arg_names: + with pytest.raises(TypeError, match='must be an instance of int or'): + net.update_weights(**{arg: 'abc'}) + + with pytest.raises(ValueError, match='must be non-negative'): + net.update_weights(**{arg: -1}) + + with pytest.raises(TypeError, match='must be an instance of bool'): + net.update_weights(copy='True') + + net_updated = net.update_weights(e_e=2.0, copy=True) + + for conn in net.connectivity: + assert conn['nc_dict']['gain'] == 1.0 + + for conn in net_updated.connectivity: + if (conn['src_type'] in e_cell_names and + conn['target_type'] in e_cell_names): + assert conn['nc_dict']['gain'] == 2.0 + else: + assert conn['nc_dict']['gain'] == 1.0 + + net.update_weights(i_e=0.5, copy=False) + for conn in net.connectivity: + if (conn['src_type'] in i_cell_names and + conn['target_type'] in e_cell_names): + assert conn['nc_dict']['gain'] == 0.5 + else: + assert conn['nc_dict']['gain'] == 1.0 + + class TestPickConnection: """Tests for the pick_connection function.""" @pytest.mark.parametrize("arg_name", From 1f040db811643670547b8f34b47d603030d17570 Mon Sep 17 00:00:00 2001 From: George Dang <53052793+gtdang@users.noreply.github.com> Date: Thu, 26 Sep 2024 12:09:47 -0400 Subject: [PATCH 02/14] tests: updated test asset jones2009_3x3_drives.json --- .../tests/assets/jones2009_3x3_drives.json | 162 ++++++++++++------ 1 file changed, 108 insertions(+), 54 deletions(-) diff --git a/hnn_core/tests/assets/jones2009_3x3_drives.json b/hnn_core/tests/assets/jones2009_3x3_drives.json index 44d85d7bc..149a86fde 100644 --- a/hnn_core/tests/assets/jones2009_3x3_drives.json +++ b/hnn_core/tests/assets/jones2009_3x3_drives.json @@ -2180,7 +2180,8 @@ "A_delay": 0.1, "A_weight": 0.006562, "lamtha": 3.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -2217,7 +2218,8 @@ "A_delay": 0.1, "A_weight": 0.019482, "lamtha": 3.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -2284,7 +2286,8 @@ "A_delay": 0.1, "A_weight": 7e-06, "lamtha": 3.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -2351,7 +2354,8 @@ "A_delay": 0.1, "A_weight": 0.004317, "lamtha": 3.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -2418,7 +2422,8 @@ "A_delay": 0.1, "A_weight": 0.1423, "lamtha": 3.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -2485,7 +2490,8 @@ "A_delay": 0.1, "A_weight": 0.080074, "lamtha": 3.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -2522,7 +2528,8 @@ "A_delay": 0.1, "A_weight": 0.08831, "lamtha": 3.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -2559,7 +2566,8 @@ "A_delay": 0.1, "A_weight": 0.0, "lamtha": 3.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -2626,7 +2634,8 @@ "A_delay": 0.1, "A_weight": 0.01525, "lamtha": 3.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -2693,7 +2702,8 @@ "A_delay": 0.1, "A_weight": 0.0, "lamtha": 3.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -2730,7 +2740,8 @@ "A_delay": 1.0, "A_weight": 0.19934, "lamtha": 3.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -2767,7 +2778,8 @@ "A_delay": 1.0, "A_weight": 0.0, "lamtha": 3.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -2834,7 +2846,8 @@ "A_delay": 1.0, "A_weight": 0.00865, "lamtha": 3.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -2901,7 +2914,8 @@ "A_delay": 1.0, "A_weight": 0.0, "lamtha": 3.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -2938,7 +2952,8 @@ "A_delay": 0.1, "A_weight": 3e-06, "lamtha": 3.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -2975,7 +2990,8 @@ "A_delay": 0.1, "A_weight": 0.0, "lamtha": 3.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -3042,7 +3058,8 @@ "A_delay": 0.1, "A_weight": 1.43884, "lamtha": 3.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -3109,7 +3126,8 @@ "A_delay": 0.1, "A_weight": 0.0, "lamtha": 3.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -3146,7 +3164,8 @@ "A_delay": 1.0, "A_weight": 0.008958, "lamtha": 3.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -3183,7 +3202,8 @@ "A_delay": 1.0, "A_weight": 0.0, "lamtha": 3.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -3250,7 +3270,8 @@ "A_delay": 1.0, "A_weight": 0.684013, "lamtha": 3.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -3317,7 +3338,8 @@ "A_delay": 1.0, "A_weight": 0.0, "lamtha": 3.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -3447,7 +3469,8 @@ "A_delay": 1.0, "A_weight": 0.0005, "lamtha": 3.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 0, "probability": 1.0 @@ -3577,7 +3600,8 @@ "A_delay": 1.0, "A_weight": 0.0005, "lamtha": 3.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 0, "probability": 1.0 @@ -3707,7 +3731,8 @@ "A_delay": 1.0, "A_weight": 0.0005, "lamtha": 3.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 0, "probability": 1.0 @@ -3837,7 +3862,8 @@ "A_delay": 1.0, "A_weight": 0.0005, "lamtha": 3.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 0, "probability": 1.0 @@ -3904,7 +3930,8 @@ "A_delay": 1.0, "A_weight": 0.05, "lamtha": 50.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -3971,7 +3998,8 @@ "A_delay": 1.0, "A_weight": 0.05, "lamtha": 50.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -4038,7 +4066,8 @@ "A_delay": 1.0, "A_weight": 0.025, "lamtha": 70.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -4105,7 +4134,8 @@ "A_delay": 1.0, "A_weight": 0.025, "lamtha": 70.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -4244,7 +4274,8 @@ "A_delay": 1.0, "A_weight": 0.00025, "lamtha": 3.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -4383,7 +4414,8 @@ "A_delay": 1.0, "A_weight": 0.00025, "lamtha": 3.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -4450,7 +4482,8 @@ "A_delay": 1.0, "A_weight": 0.001, "lamtha": 50.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -4529,7 +4562,8 @@ "A_delay": 1.0, "A_weight": 0.0005, "lamtha": 3.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -4572,7 +4606,8 @@ "A_delay": 1.0, "A_weight": 0.02, "lamtha": 20.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -4612,7 +4647,8 @@ "A_delay": 1.0, "A_weight": 0.02, "lamtha": 20.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 0, "probability": 1.0 @@ -4691,7 +4727,8 @@ "A_delay": 1.0, "A_weight": 0.0005, "lamtha": 3.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -4770,7 +4807,8 @@ "A_delay": 1.0, "A_weight": 0.00025, "lamtha": 3.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -4855,7 +4893,8 @@ "A_delay": 0.0, "A_weight": 0.0, "lamtha": 100.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -4940,7 +4979,8 @@ "A_delay": 0.0, "A_weight": 0.0, "lamtha": 100.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -5091,7 +5131,8 @@ "A_delay": 0.1, "A_weight": 5.4e-05, "lamtha": 100.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -5242,7 +5283,8 @@ "A_delay": 0.1, "A_weight": 0.0, "lamtha": 100.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -5327,7 +5369,8 @@ "A_delay": 0.0, "A_weight": 0.0, "lamtha": 100.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -5412,7 +5455,8 @@ "A_delay": 0.0, "A_weight": 0.0, "lamtha": 100.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -5563,7 +5607,8 @@ "A_delay": 1.0, "A_weight": 5.4e-05, "lamtha": 100.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -5714,7 +5759,8 @@ "A_delay": 1.0, "A_weight": 0.0, "lamtha": 100.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -5751,7 +5797,8 @@ "A_delay": 0.0, "A_weight": 0.0, "lamtha": 100.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -5788,7 +5835,8 @@ "A_delay": 0.0, "A_weight": 0.0, "lamtha": 100.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -5855,7 +5903,8 @@ "A_delay": 0.1, "A_weight": 0.0008, "lamtha": 100.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -5922,7 +5971,8 @@ "A_delay": 0.1, "A_weight": 0.0, "lamtha": 100.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -5959,7 +6009,8 @@ "A_delay": 0.0, "A_weight": 0.0, "lamtha": 100.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -5996,7 +6047,8 @@ "A_delay": 0.0, "A_weight": 0.0, "lamtha": 100.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -6063,7 +6115,8 @@ "A_delay": 1.0, "A_weight": 0.0075, "lamtha": 100.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 @@ -6130,7 +6183,8 @@ "A_delay": 1.0, "A_weight": 0.0, "lamtha": 100.0, - "threshold": 0.0 + "threshold": 0.0, + "gain": 1.0 }, "allow_autapses": 1, "probability": 1.0 From 70d1e6e65688762d4f7fa536973ffebbc62d3ab8 Mon Sep 17 00:00:00 2001 From: George Dang <53052793+gtdang@users.noreply.github.com> Date: Thu, 26 Sep 2024 12:10:31 -0400 Subject: [PATCH 03/14] test: added gain to test_conn_to_dict --- hnn_core/tests/test_io.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hnn_core/tests/test_io.py b/hnn_core/tests/test_io.py index deaeef6bd..c7dbaf8d5 100644 --- a/hnn_core/tests/test_io.py +++ b/hnn_core/tests/test_io.py @@ -268,7 +268,8 @@ def test_conn_to_dict(jones_2009_network): 'nc_dict': {'A_delay': 0.1, 'A_weight': 0.006562, 'lamtha': 3.0, - 'threshold': 0.0}, + 'threshold': 0.0, + 'gain': 1.0}, 'allow_autapses': 1, 'probability': 1.0} From 0486a40491a3fc377e8d423989470a6aba920dd9 Mon Sep 17 00:00:00 2001 From: George Dang <53052793+gtdang@users.noreply.github.com> Date: Thu, 26 Sep 2024 12:11:31 -0400 Subject: [PATCH 04/14] fix: added the update_weights method to the attributes to ignore list in the __eq__ method of the Network class --- hnn_core/network.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hnn_core/network.py b/hnn_core/network.py index 69de6d034..cd48496e1 100644 --- a/hnn_core/network.py +++ b/hnn_core/network.py @@ -473,7 +473,8 @@ def __eq__(self, other): 'clear_connectivity', 'clear_drives', 'connectivity', 'copy', 'gid_to_type', 'plot_cells', 'set_cell_positions', - 'to_dict', 'write_configuration']) + 'to_dict', 'write_configuration', + 'update_weights']) attrs_to_check = [x for x in all_attrs if x not in attrs_to_ignore] for attr in attrs_to_check: From 35f601e570232b83b22a5367ba94b68534eb9749 Mon Sep 17 00:00:00 2001 From: George Dang <53052793+gtdang@users.noreply.github.com> Date: Thu, 26 Sep 2024 12:12:54 -0400 Subject: [PATCH 05/14] refactor: removed code for generation of unused test asset file --- hnn_core/tests/test_io.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/hnn_core/tests/test_io.py b/hnn_core/tests/test_io.py index c7dbaf8d5..54d32f212 100644 --- a/hnn_core/tests/test_io.py +++ b/hnn_core/tests/test_io.py @@ -104,9 +104,6 @@ def generate_test_files(jones_2009_network): """ Generates files used in read-in tests """ net = jones_2009_network net.write_configuration(Path('.', 'assets/jones2009_3x3_drives.json')) - simulate_dipole(net, tstop=2, n_trials=1, dt=0.5) - net.write_configuration(Path('.', - 'assets/jones2009_3x3_drives_simulated.json')) def test_eq(jones_2009_network, calcium_network): From 8401a0c8df7e93e9bbfb07f5b44a5f6943efeb82 Mon Sep 17 00:00:00 2001 From: George Dang <53052793+gtdang@users.noreply.github.com> Date: Thu, 26 Sep 2024 13:36:56 -0400 Subject: [PATCH 06/14] test: updated check_equal_networks of test_gui.py This function is a stand-in function for the __eq__ method used only in the tests. --- hnn_core/tests/test_gui.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hnn_core/tests/test_gui.py b/hnn_core/tests/test_gui.py index 610226774..d6f07e808 100644 --- a/hnn_core/tests/test_gui.py +++ b/hnn_core/tests/test_gui.py @@ -103,7 +103,8 @@ def check_drive(drive1, drive2, keys): 'connectivity', 'copy', 'gid_to_type', 'plot_cells', 'set_cell_positions', 'to_dict', 'write_configuration', - 'external_drives', 'external_biases']) + 'external_drives', 'external_biases', + 'update_weights']) attrs_to_check = [x for x in all_attrs if x not in attrs_to_ignore] for attr in attrs_to_check: check_equality(getattr(net1, attr), getattr(net2, attr), From cac9ebf4737ffb500efea896be48a28213bc68d9 Mon Sep 17 00:00:00 2001 From: George Dang <53052793+gtdang@users.noreply.github.com> Date: Thu, 26 Sep 2024 13:57:06 -0400 Subject: [PATCH 07/14] test: refactored and added comments to test_synaptic_gains --- hnn_core/tests/test_network.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/hnn_core/tests/test_network.py b/hnn_core/tests/test_network.py index f2f518975..341c09213 100644 --- a/hnn_core/tests/test_network.py +++ b/hnn_core/tests/test_network.py @@ -913,18 +913,19 @@ def test_synaptic_gains(): with pytest.raises(TypeError, match='must be an instance of bool'): net.update_weights(copy='True') + # Single argument check with copy net_updated = net.update_weights(e_e=2.0, copy=True) - - for conn in net.connectivity: - assert conn['nc_dict']['gain'] == 1.0 - for conn in net_updated.connectivity: if (conn['src_type'] in e_cell_names and conn['target_type'] in e_cell_names): assert conn['nc_dict']['gain'] == 2.0 else: assert conn['nc_dict']['gain'] == 1.0 + # Ensure that the original network gains did not change + for conn in net.connectivity: + assert conn['nc_dict']['gain'] == 1.0 + # Single argument with inplace change net.update_weights(i_e=0.5, copy=False) for conn in net.connectivity: if (conn['src_type'] in i_cell_names and From 918b4a493c306cf2c20271fddb786131c1223038 Mon Sep 17 00:00:00 2001 From: George Dang <53052793+gtdang@users.noreply.github.com> Date: Thu, 26 Sep 2024 13:57:57 -0400 Subject: [PATCH 08/14] test: added test for changing two gains --- hnn_core/tests/test_network.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/hnn_core/tests/test_network.py b/hnn_core/tests/test_network.py index 341c09213..f80c21168 100644 --- a/hnn_core/tests/test_network.py +++ b/hnn_core/tests/test_network.py @@ -934,6 +934,19 @@ def test_synaptic_gains(): else: assert conn['nc_dict']['gain'] == 1.0 + # Two argument check + net.update_weights(i_e=0.5, i_i=0.25, copy=False) + for conn in net.connectivity: + if (conn['src_type'] in i_cell_names and + conn['target_type'] in e_cell_names): + assert conn['nc_dict']['gain'] == 0.5 + elif (conn['src_type'] in i_cell_names and + conn['target_type'] in i_cell_names): + assert conn['nc_dict']['gain'] == 0.25 + else: + assert conn['nc_dict']['gain'] == 1.0 + + class TestPickConnection: """Tests for the pick_connection function.""" From a4c6a8b52b38fece4f151678d34ef48aace6bdf5 Mon Sep 17 00:00:00 2001 From: George Dang <53052793+gtdang@users.noreply.github.com> Date: Thu, 26 Sep 2024 17:47:22 -0400 Subject: [PATCH 09/14] test: added spot check to see if NetworkBuilder weights are multiplied correctly by the set gains --- hnn_core/tests/test_network.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/hnn_core/tests/test_network.py b/hnn_core/tests/test_network.py index f80c21168..8878f4bd9 100644 --- a/hnn_core/tests/test_network.py +++ b/hnn_core/tests/test_network.py @@ -898,6 +898,7 @@ def test_network_mesh(): def test_synaptic_gains(): """Test synaptic gains update""" net = jones_2009_model() + nb_base = NetworkBuilder(net) e_cell_names = ['L2_pyramidal', 'L5_pyramidal'] i_cell_names = ['L2_basket', 'L5_basket'] @@ -946,6 +947,19 @@ def test_synaptic_gains(): else: assert conn['nc_dict']['gain'] == 1.0 + nb_updated = NetworkBuilder(net) + # Check weights are altered + def _get_weight(nb, conn_name, idx=0): + return nb.ncs[conn_name][idx].weight[0] + # i_e check + assert (_get_weight(nb_updated, 'L2Basket_L2Pyr_gabaa') / + _get_weight(nb_base, 'L2Basket_L2Pyr_gabaa')) == 0.5 + # i_i check + assert (_get_weight(nb_updated, 'L2Basket_L2Basket_gabaa') / + _get_weight(nb_base, 'L2Basket_L2Basket_gabaa')) == 0.25 + # Unaltered check + assert (_get_weight(nb_updated, 'L2Pyr_L5Basket_ampa') / + _get_weight(nb_base, 'L2Pyr_L5Basket_ampa')) == 1 class TestPickConnection: From 01594086e7fcadbe871421503bc9e8fca68fe089 Mon Sep 17 00:00:00 2001 From: George Dang <53052793+gtdang@users.noreply.github.com> Date: Thu, 26 Sep 2024 18:03:30 -0400 Subject: [PATCH 10/14] refactor: flake8 --- hnn_core/tests/test_network.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hnn_core/tests/test_network.py b/hnn_core/tests/test_network.py index 8878f4bd9..5b7d7a742 100644 --- a/hnn_core/tests/test_network.py +++ b/hnn_core/tests/test_network.py @@ -947,10 +947,11 @@ def test_synaptic_gains(): else: assert conn['nc_dict']['gain'] == 1.0 - nb_updated = NetworkBuilder(net) # Check weights are altered def _get_weight(nb, conn_name, idx=0): return nb.ncs[conn_name][idx].weight[0] + + nb_updated = NetworkBuilder(net) # i_e check assert (_get_weight(nb_updated, 'L2Basket_L2Pyr_gabaa') / _get_weight(nb_base, 'L2Basket_L2Pyr_gabaa')) == 0.5 From e271d2e47d13485b85c96fb89e2c1abdf9133696 Mon Sep 17 00:00:00 2001 From: Nicholas Tolley Date: Fri, 27 Sep 2024 11:40:12 -0400 Subject: [PATCH 11/14] update whats_new --- doc/whats_new.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/whats_new.rst b/doc/whats_new.rst index 229b2fca0..a25457c69 100644 --- a/doc/whats_new.rst +++ b/doc/whats_new.rst @@ -18,6 +18,8 @@ Changelog - Add minimum spectral frequency widget to GUI for adjusting spectrogram frequency axis, by `George Dang`_ in :gh:`894` +- Add method to modify synaptic gains, by `Nick Tolley`_ and `George Dang`_ + in :gh:`897` Bug ~~~ From 7acf56da91106c09d790c794fd1398563a0d3d1b Mon Sep 17 00:00:00 2001 From: Nicholas Tolley Date: Fri, 27 Sep 2024 14:05:09 -0400 Subject: [PATCH 12/14] Pass None as default --- hnn_core/network.py | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/hnn_core/network.py b/hnn_core/network.py index cd48496e1..c8ca8de0e 100644 --- a/hnn_core/network.py +++ b/hnn_core/network.py @@ -1431,22 +1431,40 @@ def add_electrode_array(self, name, electrode_pos, *, conductivity=0.3, method=method, min_distance=min_distance)}) - def update_weights(self, e_e=1.0, e_i=1.0, i_e=1.0, i_i=1.0, copy=True): + def update_weights(self, e_e=None, e_i=None, + i_e=None, i_i=None, copy=True): """Update synaptic weights of the network. Parameters ---------- e_e : float - Synaptic gain of excitatory to excitatory connections (default 1.0) + Synaptic gain of excitatory to excitatory connections + (default None) e_i : float - Synaptic gain of excitatory to inhibitory connections (default 1.0) + Synaptic gain of excitatory to inhibitory connections + (default None) i_e : float - Synaptic gain of inhibitory to excitatory connections (default 1.0) + Synaptic gain of inhibitory to excitatory connections + (default None) i_i : float - Synaptic gain of inhibitory to inhibitory connections (default 1.0) + Synaptic gain of inhibitory to inhibitory connections + (default None) copy : bool - If True, create a copy of the network. If False, update the network - in place (default True) + If True, returns a copy of the network. If False, + the network is updated in place with a return of None. + + + Returns + ------- + net : instance of Network + A copy of the instance with updated synaptic gains if copy=True. + + Notes + ----- + Synaptic gains must be non-negative. The synaptic gains will only be + updated if a float value is provided. If None is provided + (the default), the synapticgain will remain unchanged. + """ _validate_type(copy, bool, 'copy') @@ -1467,6 +1485,9 @@ def update_weights(self, e_e=1.0, e_i=1.0, i_e=1.0, i_i=1.0, copy=True): } for conn_type, (gain, e_vals, i_vals) in conn_types.items(): + if gain is None: + continue + _validate_type(gain, (int, float), conn_type, 'int or float') if gain < 0.0: raise ValueError("Synaptic gains must be non-negative." From ba48c62283c50d3a086f2e2426b83c1174f30526 Mon Sep 17 00:00:00 2001 From: Nicholas Tolley Date: Fri, 27 Sep 2024 14:05:29 -0400 Subject: [PATCH 13/14] docstring spacing --- hnn_core/network.py | 1 - 1 file changed, 1 deletion(-) diff --git a/hnn_core/network.py b/hnn_core/network.py index c8ca8de0e..95589c214 100644 --- a/hnn_core/network.py +++ b/hnn_core/network.py @@ -1453,7 +1453,6 @@ def update_weights(self, e_e=None, e_i=None, If True, returns a copy of the network. If False, the network is updated in place with a return of None. - Returns ------- net : instance of Network From 1bc8eb03a9d6d3b5ef49fd92c23320649336230a Mon Sep 17 00:00:00 2001 From: Nicholas Tolley Date: Fri, 27 Sep 2024 15:23:57 -0400 Subject: [PATCH 14/14] copy default to false --- hnn_core/network.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hnn_core/network.py b/hnn_core/network.py index 95589c214..a9222ce9e 100644 --- a/hnn_core/network.py +++ b/hnn_core/network.py @@ -1432,7 +1432,7 @@ def add_electrode_array(self, name, electrode_pos, *, conductivity=0.3, min_distance=min_distance)}) def update_weights(self, e_e=None, e_i=None, - i_e=None, i_i=None, copy=True): + i_e=None, i_i=None, copy=False): """Update synaptic weights of the network. Parameters @@ -1452,6 +1452,7 @@ def update_weights(self, e_e=None, e_i=None, copy : bool If True, returns a copy of the network. If False, the network is updated in place with a return of None. + (default False) Returns -------