From 6c464168a4c7a863e540a8c1a0ea31f7437db34d Mon Sep 17 00:00:00 2001 From: Xi Zhang Date: Mon, 15 Sep 2025 17:26:51 -0400 Subject: [PATCH 1/3] update the existing test cases, and add the new test case --- tests/test_synapse_and_soma_models.py | 123 +++++++++++++++++++------- tests/util.py | 4 +- 2 files changed, 92 insertions(+), 35 deletions(-) diff --git a/tests/test_synapse_and_soma_models.py b/tests/test_synapse_and_soma_models.py index e99fa9f..0b29d74 100644 --- a/tests/test_synapse_and_soma_models.py +++ b/tests/test_synapse_and_soma_models.py @@ -6,7 +6,8 @@ import inspect from pathlib import Path - +import matplotlib +matplotlib.use('Agg') # Use non-interactive backend for headless environments from matplotlib import pyplot as plt from superneuroabm.model import NeuromorphicModel @@ -35,9 +36,6 @@ def __init__(self, methodName: str = ...) -> None: super().__init__(methodName) # Create NeuromorphicModel instance for testing self._model = NeuromorphicModel() - # Set global simulation parameters - self._model.register_global_property("dt", 1e-3) # Time step (100 μs) - self._model.register_global_property("I_bias", 0) # No bias current # Set to use CPU for base test (GPU variant in separate class) self._use_gpu = True @@ -86,6 +84,90 @@ def test_izh_soma_single_exp_synapse(self) -> None: "izh_soma", "config_0", "single_exp_synapse", "no_learning_config_0" ) + def test_lif_soma_multi_synapse_integration(self) -> None: + """ + Tests multi-synapse integration with a two-soma network. + + This test creates a neural circuit: + - External input (synapse_0) -> soma_0 -> synapse_1 -> soma_1 + - External input (synapse_2) -> soma_1 + + This verifies that soma_1 can integrate inputs from both an internal synapse + (from soma_0) and an external synapse (synapse_2) simultaneously. + """ + + # Create soma_0 (LIF) + soma_0 = self._model.create_soma( + breed="lif_soma", + config_name="config_0", + ) + + # Create soma_1 (LIF) + soma_1 = self._model.create_soma( + breed="lif_soma", + config_name="config_0", + ) + + # Create synapse_0: external input -> soma_0 + synapse_0 = self._model.create_synapse( + breed="single_exp_synapse", + pre_soma_id=np.nan, # External input + post_soma_id=soma_0, + config_name="no_learning_config_0", + ) + + # Create synapse_1: soma_0 -> soma_1 + synapse_1 = self._model.create_synapse( + breed="single_exp_synapse", + pre_soma_id=soma_0, + post_soma_id=soma_1, + config_name="no_learning_config_0", + ) + + # Create synapse_2: external input -> soma_1 + synapse_2 = self._model.create_synapse( + breed="single_exp_synapse", + pre_soma_id=np.nan, # External input + post_soma_id=soma_1, + config_name="no_learning_config_0", + ) + + # Initialize the simulation environment + self._model.setup(use_gpu=self._use_gpu) + + # Inject spikes into synapse_0 (external -> soma_0) + for spike in self._spike_times[0]: + self._model.add_spike(synapse_id=synapse_0, tick=spike[0], value=spike[1]) + + # Inject spikes into synapse_2 (external -> soma_1) using second spike pattern + for spike in self._spike_times[1]: + self._model.add_spike(synapse_id=synapse_2, tick=spike[0], value=spike[1]) + + # Run simulation + self._model.simulate( + ticks=self._simulation_duration, update_data_ticks=self._sync_every_n_ticks + ) + + # Extract internal states for analysis + internal_states_syn0 = np.array( + self._model.get_internal_states_history(agent_id=synapse_0) + ) + internal_states_syn1 = np.array( + self._model.get_internal_states_history(agent_id=synapse_1) + ) + internal_states_syn2 = np.array( + self._model.get_internal_states_history(agent_id=synapse_2) + ) + + # Generate visualization + caller_name = inspect.stack()[0].function + vizualize_responses(self._model, vthr=0, fig_name=f"{caller_name}.png") + + # Verify that soma_1 received inputs from both synapses + # soma_1 should have activity from both internal (synapse_1) and external (synapse_2) inputs + assert internal_states_syn1.size > 0, "Synapse 1 (soma_0->soma_1) should have activity" + assert internal_states_syn2.size > 0, "Synapse 2 (ext->soma_1) should have activity" + def micro_model_test_helper( self, soma_breed: str, soma_config: str, synapse_breed: str, synapse_config: str ) -> None: @@ -103,34 +185,10 @@ def micro_model_test_helper( The test injects predefined spike patterns and verifies the soma's response. """ - soma_parameters = self._component_configurations["soma"][soma_breed][ - soma_config - ]["hyperparameters"] - soma_parameters = [float(val) for val in soma_parameters.values()] - soma_internal_state = self._component_configurations["soma"][soma_breed][ - soma_config - ]["default_internal_state"] - soma_internal_state = [float(val) for val in soma_internal_state.values()] - - # Create soma with specified breed and parameters + # Create soma with specified breed and config soma_0 = self._model.create_soma( breed=soma_breed, - parameters=soma_parameters, - default_internal_state=soma_internal_state, - ) - - # Package parameters for synapse creation - synapse_parameters = self._component_configurations["synapse"][synapse_breed][ - synapse_config - ]["hyperparameters"] - synapse_parameters = [float(val) for val in synapse_parameters.values()] - synapse_internal_state = self._component_configurations["synapse"][ - synapse_breed - ][synapse_config]["default_internal_state"] - synapse_internal_state = [float(val) for val in synapse_internal_state.values()] - print( - f"Soma parameters: {soma_parameters}" - f"\nSynapse parameters: {synapse_parameters}" + config_name=soma_config, ) # Create synapse connecting external input to soma @@ -138,8 +196,7 @@ def micro_model_test_helper( breed=synapse_breed, pre_soma_id=np.nan, # External input post_soma_id=soma_0, # Connected to the created soma - parameters=synapse_parameters, - default_internal_state=synapse_internal_state, + config_name=synapse_config, ) # Initialize the simulation environment @@ -166,7 +223,7 @@ def micro_model_test_helper( # Generate visualization of responses over time caller_name = inspect.stack()[1].function - vizualize_responses(self._model, vthr=0, fig_name=f"{caller_name}.png") + vizualize_responses(self._model, vthr=0, fig_name=f"{caller_name}.png", figsize=(8, 20)) # Assert that the neuron generated expected number of spikes '''actual_spikes = len(self._model.get_spike_times(soma_id=soma_0)) diff --git a/tests/util.py b/tests/util.py index 7647bf2..12383a2 100644 --- a/tests/util.py +++ b/tests/util.py @@ -5,13 +5,13 @@ from superneuroabm.model import NeuromorphicModel -def vizualize_responses(model: NeuromorphicModel, vthr: int, fig_name: str) -> None: +def vizualize_responses(model: NeuromorphicModel, vthr: int, fig_name: str, figsize=(12,8)) -> None: soma_ids = model.soma2synapse_map.keys() synapse_ids = model.synapse2soma_map.keys() # Generate visualization comparing membrane potential and synaptic currents - plt.figure(figsize=(12, 8)) + plt.figure(figsize=figsize) total_plot_count = len(soma_ids) + len(synapse_ids) * 3 From 36877e0c9857247cfb5b885f3ae0dde7a8759275 Mon Sep 17 00:00:00 2001 From: wfishell Date: Tue, 16 Sep 2025 22:39:07 +0000 Subject: [PATCH 2/3] updates to logic gates test and yaml file. succesfully tested on v100 gpu. Yaml file changes also tested with other test no issues --- superneuroabm/component_base_config.yaml | 16 +- tests/logic_gates_test_lif.py | 603 +++++++---------------- 2 files changed, 199 insertions(+), 420 deletions(-) diff --git a/superneuroabm/component_base_config.yaml b/superneuroabm/component_base_config.yaml index 32be354..b9854fa 100644 --- a/superneuroabm/component_base_config.yaml +++ b/superneuroabm/component_base_config.yaml @@ -20,7 +20,7 @@ soma: hyperparameters: k: 1.2 vthr: -45 - C: 150 + C: 15 a: 0.01 b: 5 vpeak: 50 @@ -36,26 +36,30 @@ synapse: single_exp_synapse: no_learning_config_0: hyperparameters: - weight: 14.0 # Synaptic weight (strength) + weight: 15.0 # Synaptic weight (strength) synaptic_delay: 1.0 # Transmission delay (ms) scale: 1.0 # Scaling factor tau_fall: 1e-2 # Decay time constant (1 ms) tau_rise: 0 # Rise time constant (instantaneous) internal_state: - I_synapse: 0.0 # Initial synaptic current + I_synapse: 1.0 # Initial synaptic current learning_hyperparameters: stdp_type: -1 # No learning + internal_learning_state: + pre_trace: 0 # Pre-synaptic trace + post_trace: 0 # Post-synaptic trace + dW: 0 exp_pair_wise_stdp_config_0: hyperparameters: - weight: 14.0 # Synaptic weight (strength) + weight: 5.0 # Synaptic weight (strength) synaptic_delay: 1.0 # Transmission delay (ms) scale: 1.0 # Scaling factor tau_fall: 1e-2 # Decay time constant (1 ms) tau_rise: 0 # Rise time constant (instantaneous) internal_state: - I_synapse: 0.0 # Initial synaptic current + I_synapse: 1.0 # Initial synaptic current learning_hyperparameters: - stdp_type: 0 # Exp pair-wise STDP + stdp_type: 10e-3 # Exp pair-wise STDP tau_pre_stdp: 10e-3 # Pre-synaptic STDP time constant (10 ms) tau_post_stdp: 10e-3 # Post-synaptic STDP time constant (10 ms) a_exp_pre: 0.005 # Pre-synaptic STDP learning rate diff --git a/tests/logic_gates_test_lif.py b/tests/logic_gates_test_lif.py index d29f9ad..d760d99 100644 --- a/tests/logic_gates_test_lif.py +++ b/tests/logic_gates_test_lif.py @@ -5,7 +5,7 @@ from superneuroabm.model import NeuromorphicModel from matplotlib import pyplot as plt - +import yaml class LogicGatesTestLIF(unittest.TestCase): """ @@ -17,6 +17,8 @@ class LogicGatesTestLIF(unittest.TestCase): """ def __init__(self, methodName: str = ...) -> None: + with open("superneuroabm/component_base_config.yaml", "r") as f: + self.data = yaml.safe_load(f) """ Initialize the test case with a NeuromorphicModel instance. @@ -27,7 +29,7 @@ def __init__(self, methodName: str = ...) -> None: # Create NeuromorphicModel instance for testing self._model = NeuromorphicModel() # Set to use CPU for base test (GPU variant in separate class) - self._use_gpu = False + self._use_gpu = True def test_two_somas(self): """ @@ -44,82 +46,61 @@ def test_two_somas(self): self._model.register_global_property("dt", 1e-1) # Time step (100 μs) self._model.register_global_property("I_bias", 0) # No bias current - # Define LIF neuron parameters - C = 10e-9 # Membrane capacitance in Farads (10 nF) - R = 1e12 # Membrane resistance in Ohms (1 TΩ) - vthr = -45 # Spike threshold voltage (mV) - tref = 5e-3 # Refractory period (5 ms) - vrest = -60 # Resting potential (mV) - vreset = -60 # Reset potential after spike (mV) - tref_allows_integration = ( - 1 # Whether to allow integration during refractory period - ) - I_in = 4e-8 # Input current (40 nA) # Package parameters for soma creation - soma_parameters = [ - C, - R, - vthr, - tref, - vrest, - vreset, - tref_allows_integration, - I_in, - ] - - # Set initial internal state for neurons - v = vrest # Initial membrane voltage - tcount = 0 # Time counter - tlast = 0 # Last spike time - default_internal_state = [v, tcount, tlast] + soma_parameters = self.data['soma']['lif_soma']['config_0']['hyperparameters'] + + default_internal_state = self.data['soma']['lif_soma']['config_0']['internal_state'] # Create first LIF neuron (receives external input) soma_0 = self._model.create_soma( - breed="LIF_Soma", - parameters=soma_parameters, - default_internal_state=default_internal_state, + breed="lif_soma", + config_name='config_0', + hyperparameters_overrides= soma_parameters, + default_internal_state_overrides=default_internal_state, ) # Create second LIF neuron (receives input from soma_0) soma_1 = self._model.create_soma( - breed="LIF_Soma", - parameters=soma_parameters, - default_internal_state=default_internal_state, + breed="lif_soma", + config_name='config_0', + hyperparameters_overrides=soma_parameters, + default_internal_state_overrides=default_internal_state, ) - # Define synaptic parameters for connections - weight = 1.0 # Synaptic weight (strength) - synaptic_delay = 1.0 # Transmission delay (ms) - scale = 1.0 # Scaling factor - tau_fall = 1e-3 # Decay time constant (1 ms) - tau_rise = 0 # Rise time constant (instantaneous) - synapse_parameters = [ - weight, - synaptic_delay, - scale, - tau_fall, - tau_rise, - ] - - # Initial synaptic current - I_synapse = 0.0 - synapse_internal_state = [I_synapse] - - # Create external input synapse (stimulates soma_0) + #LEARNING PARAMETERS A + synapse_parameters_A=self.data['synapse']['single_exp_synapse']['exp_pair_wise_stdp_config_0']['hyperparameters'] + synapse_internal_state_A=self.data['synapse']['single_exp_synapse']['exp_pair_wise_stdp_config_0']['internal_state'] + learning_parameters_A=self.data['synapse']['single_exp_synapse']['exp_pair_wise_stdp_config_0']['learning_hyperparameters'] + internal_learning_state_A=self.data['synapse']['single_exp_synapse']['exp_pair_wise_stdp_config_0']['internal_learning_state'] + #LEARNING PARAMETERS B + synapse_parameters_B=self.data['synapse']['single_exp_synapse']['no_learning_config_0']['hyperparameters'] + synapse_internal_state_B=self.data['synapse']['single_exp_synapse']['no_learning_config_0']['internal_state'] + learning_parameters_B=self.data['synapse']['single_exp_synapse']['no_learning_config_0']['learning_hyperparameters'] + + + + # Create first external input synapse (stronger input) syn_ext = self._model.create_synapse( - breed="Single_Exp_Synapse", + breed="single_exp_synapse", pre_soma_id=np.nan, # External input (no pre-synaptic neuron) post_soma_id=soma_0, - parameters=synapse_parameters, - default_internal_state=synapse_internal_state, + config_name='exp_pair_wise_stdp_config_0', + hyperparameters_overrides=synapse_parameters_A, + default_internal_state_overrides=synapse_internal_state_A, + learning_hyperparameters_overrides=learning_parameters_A, + default_internal_learning_state_overrides=internal_learning_state_A ) + # Create internal synapse (soma_0 -> soma_1) syn_int = self._model.create_synapse( - breed="Single_Exp_Synapse", + breed="single_exp_synapse", pre_soma_id=soma_0, post_soma_id=soma_1, - parameters=synapse_parameters, - default_internal_state=synapse_internal_state, + config_name='exp_pair_wise_stdp_config_0', + hyperparameters_overrides=synapse_parameters_B, + default_internal_state_overrides=synapse_internal_state_B, + learning_hyperparameters_overrides=learning_parameters_B, + default_internal_learning_state_overrides=internal_learning_state_A ) # Initialize the simulation environment @@ -202,41 +183,18 @@ def test_synapse(self): self._model.register_global_property("dt", 1e-3) # Time step (100 μs) self._model.register_global_property("I_bias", 0) # No bias current - # Define LIF neuron parameters - C = 10e-9 # Membrane capacitance in Farads (10 nF) - R = 1e6 # Membrane resistance in Ohms (1 TΩ) - vthr = -45 # Spike threshold voltage (mV) - tref = 5e-3 # Refractory period (5 ms) - vrest = -60 # Resting potential (mV) - vreset = -70 # Reset potential after spike (mV) - tref_allows_integration = ( - 1 # Whether to allow integration during refractory period - ) - I_in = 0 # Input current (40 nA) # Package parameters for soma creation - soma_parameters = [ - C, - R, - vthr, - tref, - vrest, - vreset, - tref_allows_integration, - I_in, - ] - - # Set initial internal state for neurons - v = vrest # Initial membrane voltage - tcount = 0 # Time counter - tlast = 0 # Last spike time - default_internal_state = [v, tcount, tlast, 0] + soma_parameters = self.data['soma']['lif_soma']['config_0']['hyperparameters'] + + default_internal_state = self.data['soma']['lif_soma']['config_0']['internal_state'] # Create first LIF neuron (receives external input) soma_0 = self._model.create_soma( - breed="LIF_Soma", - parameters=soma_parameters, - default_internal_state=default_internal_state, + breed="lif_soma", + config_name='config_0', + hyperparameters_overrides=soma_parameters, + default_internal_state_overrides=default_internal_state, ) # # Create second LIF neuron (receives input from soma_0) # soma_1 = self._model.create_soma( @@ -246,53 +204,29 @@ def test_synapse(self): # ) # Define synaptic parameters for connections - weight = 2.0 # Synaptic weight (strength) - synaptic_delay = 1.0 # Transmission delay (ms) - scale = 1.0 # Scaling factor - tau_fall = 1e-2 # Decay time constant (1 ms) - tau_rise = 0 # Rise time constant (instantaneous) - synapse_parameters = [ - weight, - synaptic_delay, - scale, - tau_fall, - tau_rise, - ] - - # Initial synaptic current - I_synapse = 0.0 - synapse_internal_state = [I_synapse] - - # Define STDP learning parameters - stdpType = -1 # Exp pair-wise STDP - tau_pre_stdp = 10e-3 # Pre-synaptic STDP time constant (10 ms) - tau_post_stdp = 10e-3 # Post-synaptic STDP time constant (10 ms) - a_exp_pre = 0.005 # Pre-synaptic STDP learning rate - a_exp_post = 0.005 # Post-synaptic STDP learning rate - stdp_history_length = 100 # Length of STDP history buffer - learning_parameters_0 = [ - stdpType, - tau_pre_stdp, - tau_post_stdp, - a_exp_pre, - a_exp_post, - stdp_history_length, - ] - # Internal learning state for STDP synapses - pre_trace = 0 - post_trace = 0 - dW = 0 - internal_learning_state_0 = [pre_trace, post_trace, dW] - - # Create external input synapse (stimulates soma_0) + + #LEARNING PARAMETERS A + synapse_parameters_A=self.data['synapse']['single_exp_synapse']['exp_pair_wise_stdp_config_0']['hyperparameters'] + synapse_internal_state_A=self.data['synapse']['single_exp_synapse']['exp_pair_wise_stdp_config_0']['internal_state'] + learning_parameters_A=self.data['synapse']['single_exp_synapse']['exp_pair_wise_stdp_config_0']['learning_hyperparameters'] + internal_learning_state_A=self.data['synapse']['single_exp_synapse']['exp_pair_wise_stdp_config_0']['internal_learning_state'] + #LEARNING PARAMETERS B + synapse_parameters_B=self.data['synapse']['single_exp_synapse']['no_learning_config_0']['hyperparameters'] + synapse_internal_state_B=self.data['synapse']['single_exp_synapse']['no_learning_config_0']['internal_state'] + learning_parameters_B=self.data['synapse']['single_exp_synapse']['no_learning_config_0']['learning_hyperparameters'] + + + + # Create first external input synapse (stronger input) syn_ext = self._model.create_synapse( - breed="Single_Exp_Synapse", + breed="single_exp_synapse", pre_soma_id=np.nan, # External input (no pre-synaptic neuron) post_soma_id=soma_0, - parameters=synapse_parameters, - default_internal_state=synapse_internal_state, - learning_parameters=learning_parameters_0, - default_internal_learning_state=internal_learning_state_0, + config_name = 'exp_pair_wise_stdp_config_0', + hyperparameters_overrides=synapse_parameters_A, + default_internal_state_overrides=synapse_internal_state_A, + learning_hyperparameters_overrides=learning_parameters_A, + default_internal_learning_state_overrides=internal_learning_state_A ) # Initialize the simulation environment @@ -330,7 +264,7 @@ def test_synapse(self): # Plot membrane potential plt.subplot(2, 1, 1) plt.plot(internal_states_history_soma0[:, 0], "b-", label="Soma 0") - plt.axhline(y=vthr, color="r", linestyle="--", label="Threshold") + plt.axhline(y=soma_parameters['vthr'], color="r", linestyle="--", label="Threshold") plt.ylabel("Membrane Pot. (mV)") plt.title("Soma 0") plt.legend() @@ -405,97 +339,63 @@ def test_dual_external_synapses(self): self._model.register_global_property("dt", 1e-1) # Time step (100 μs) self._model.register_global_property("I_bias", 0) # No bias current - # Define LIF neuron parameters - C = 10e-9 # Membrane capacitance in Farads (10 nF) - R = 1e12 # Membrane resistance in Ohms (1 TΩ) - vthr = -45 # Spike threshold voltage (mV) - tref = 5e-3 # Refractory period (5 ms) - vrest = -60 # Resting potential (mV) - vreset = -60 # Reset potential after spike (mV) - tref_allows_integration = 1 # Allow integration during refractory period - I_in = 0 # No direct input current (only synaptic input) # Package parameters for soma creation - soma_parameters = [ - C, - R, - vthr, - tref, - vrest, - vreset, - tref_allows_integration, - I_in, - ] - - # Set initial internal state for neuron - v = vrest # Initial membrane voltage - tcount = 0 # Time counter - tlast = 0 # Last spike time - default_internal_state = [v, tcount, tlast, 0] + soma_parameters = self.data['soma']['lif_soma']['config_0']['hyperparameters'] + + default_internal_state = self.data['soma']['lif_soma']['config_0']['internal_state'] # Create single LIF neuron that will receive dual inputs soma_0 = self._model.create_soma( - breed="LIF_Soma", - parameters=soma_parameters, - default_internal_state=default_internal_state, + breed="lif_soma", + config_name='config_0', + hyperparameters_overrides=soma_parameters, + default_internal_state_overrides=default_internal_state, ) - # Define synaptic parameters for first synapse (stronger weight) - weight_A = 2.0 # Stronger synaptic weight - synaptic_delay_A = 1.0 # Transmission delay (ms) - scale_A = 1.0 # Scaling factor - tau_fall_A = 1 # Decay time constant (2 ms) - tau_rise_A = 0 # Rise time constant (instantaneous) - synapse_parameters_A = [ - weight_A, - synaptic_delay_A, - scale_A, - tau_fall_A, - tau_rise_A, - ] - - # Define synaptic parameters for second synapse (weaker weight) - weight_B = 1.0 # Weaker synaptic weight - synaptic_delay_B = 1.0 # Longer transmission delay (ms) - scale_B = 1.0 # Scaling factor - tau_fall_B = 1 # Faster decay time constant (1 ms) - tau_rise_B = 0 # Rise time constant (instantaneous) - synapse_parameters_B = [ - weight_B, - synaptic_delay_B, - scale_B, - tau_fall_B, - tau_rise_B, - ] - - # Initial synaptic current for both synapses - I_synapse = 0.0 - synapse_internal_state = [I_synapse] + #LEARNING PARAMETERS A + synapse_parameters_A=self.data['synapse']['single_exp_synapse']['exp_pair_wise_stdp_config_0']['hyperparameters'] + synapse_internal_state_A=self.data['synapse']['single_exp_synapse']['exp_pair_wise_stdp_config_0']['internal_state'] + learning_parameters_A=self.data['synapse']['single_exp_synapse']['exp_pair_wise_stdp_config_0']['learning_hyperparameters'] + internal_learning_state_A=self.data['synapse']['single_exp_synapse']['exp_pair_wise_stdp_config_0']['internal_learning_state'] + #LEARNING PARAMETERS B + synapse_parameters_B=self.data['synapse']['single_exp_synapse']['no_learning_config_0']['hyperparameters'] + synapse_internal_state_B=self.data['synapse']['single_exp_synapse']['no_learning_config_0']['internal_state'] + learning_parameters_B=self.data['synapse']['single_exp_synapse']['no_learning_config_0']['learning_hyperparameters'] + + # Create first external input synapse (stronger input) syn_ext_A = self._model.create_synapse( - breed="Single_Exp_Synapse", + breed="single_exp_synapse", pre_soma_id=np.nan, # External input (no pre-synaptic neuron) post_soma_id=soma_0, - parameters=synapse_parameters_A, - default_internal_state=synapse_internal_state, + config_name = 'exp_pair_wise_stdp_config_0', + hyperparameters_overrides=synapse_parameters_A, + default_internal_state_overrides=synapse_internal_state_A, + learning_hyperparameters_overrides=learning_parameters_A, + default_internal_learning_state_overrides=internal_learning_state_A ) # Create second external input synapse (weaker input) syn_ext_B = self._model.create_synapse( - breed="Single_Exp_Synapse", + breed="single_exp_synapse", pre_soma_id=np.nan, # External input (no pre-synaptic neuron) post_soma_id=soma_0, - parameters=synapse_parameters_B, - default_internal_state=synapse_internal_state, + config_name = 'exp_pair_wise_stdp_config_0', + hyperparameters_overrides=synapse_parameters_B, + default_internal_state_overrides=synapse_internal_state_B, + learning_hyperparameters_overrides=learning_parameters_B, + default_internal_learning_state_overrides=internal_learning_state_A ) + # Initialize the simulation environment self._model.setup(use_gpu=self._use_gpu) # Define input spike patterns for both synapses # Synapse A receives early, strong spikes - spikes_A = [(2, 1), (10, 1), (20, 1)] # (time_tick, spike_value) + spikes_A = [(2, 1), (3,1), (6,1) ,(10, 1), (20, 1)] # (time_tick, spike_value) # Synapse B receives delayed, weaker spikes that overlap with A spikes_B = [(5, 1), (12, 1), (25, 1)] # (time_tick, spike_value) @@ -535,7 +435,7 @@ def test_dual_external_synapses(self): # Plot membrane potential plt.subplot(3, 1, 1) plt.plot(internal_states_history_soma0[:, 0], "b-", label="Membrane Potential") - plt.axhline(y=vthr, color="r", linestyle="--", label="Threshold") + plt.axhline(y=soma_parameters['vthr'], color="r", linestyle="--", label="Threshold") plt.ylabel("Membrane Pot. (mV)") plt.title("Dual Synapse Input Integration") plt.legend() @@ -589,7 +489,6 @@ def test_dual_external_synapses(self): ) # Write complete soma internal states writer.writerows(internal_states_history_soma0) - # Verify that soma responds to dual inputs actual_spikes = len(self._model.get_spike_times(soma_id=soma_0)) @@ -631,120 +530,76 @@ def test_dual_external_synapses_dual_somas(self): self._model.register_global_property("dt", 1e-3) # Time step (100 μs) self._model.register_global_property("I_bias", 0) # No bias current - # Define LIF neuron parameters - C = 10e-9 # Membrane capacitance in Farads (10 nF) - R = 1e6 # Membrane resistance in Ohms (1 TΩ) - vthr = -45 # Spike threshold voltage (mV) - tref = 5e-3 # Refractory period (5 ms) - vrest = -60 # Resting potential (mV) - vreset = -70 # Reset potential after spike (mV) - tref_allows_integration = 1 # Allow integration during refractory period - I_in = 0 # No direct input current (only synaptic input) - # Package parameters for soma creation - soma_parameters_0 = [ - C, - R, - vthr, - tref, - vrest, - vreset, - tref_allows_integration, - I_in, - ] - - # Set initial internal state for neuron - v = vrest # Initial membrane voltage - tcount = 0 # Time counter - tlast = 0 # Last spike time - default_internal_state_0 = [v, tcount, tlast, 0] + soma_parameters = self.data['soma']['lif_soma']['config_0']['hyperparameters'] + + default_internal_state = self.data['soma']['lif_soma']['config_0']['internal_state'] # Create single LIF neuron that will receive dual inputs soma_0 = self._model.create_soma( - breed="LIF_Soma", - parameters=soma_parameters_0, - default_internal_state=default_internal_state_0, + breed="lif_soma", + config_name='config_0', + hyperparameters_overrides=soma_parameters, + default_internal_state_overrides=default_internal_state, ) # Create IZH soma - k = 1.2 - vthr = -45 - C = 150 - a = 0.01 - b = 5 - vpeak = 50 - vrest = -75 - d = 130 - vreset = -56 - I_in = 350 - soma_parameters_1 = [k, vthr, C, a, b, vpeak, vrest, d, vreset, I_in] - v = vrest - u = 0 - default_internal_state_1 = [v, u] + izh_soma_parameters = self.data['soma']['izh_soma']['config_0']['hyperparameters'] + izh_default_internal_state = self.data['soma']['izh_soma']['config_0']['internal_state'] soma_1 = self._model.create_soma( - breed="IZH_Soma", - parameters=soma_parameters_1, - default_internal_state=default_internal_state_1, + breed="izh_soma", + config_name='config_0', + hyperparameters_overrides=izh_soma_parameters, + default_internal_state_overrides=izh_default_internal_state, ) - # Define synaptic parameters for first synapse (stronger weight) - weight_A = 2.0 # Stronger synaptic weight - synaptic_delay_A = 1.0 # Transmission delay (ms) - scale_A = 1.0 # Scaling factor - tau_fall_A = 1e-2 # Decay time constant (2 ms) - tau_rise_A = 0 # Rise time constant (instantaneous) - synapse_parameters_A = [ - weight_A, - synaptic_delay_A, - scale_A, - tau_fall_A, - tau_rise_A, - ] - - # Define synaptic parameters for second synapse (weaker weight) - weight_B = 1.0 # Weaker synaptic weight - synaptic_delay_B = 1.0 # Longer transmission delay (ms) - scale_B = 1.0 # Scaling factor - tau_fall_B = 1e-2 # Faster decay time constant (1 ms) - tau_rise_B = 0 # Rise time constant (instantaneous) - synapse_parameters_B = [ - weight_B, - synaptic_delay_B, - scale_B, - tau_fall_B, - tau_rise_B, - ] - - # Initial synaptic current for both synapses - I_synapse = 0.0 - synapse_internal_state = [I_synapse] + #LEARNING PARAMETERS A + synapse_parameters_A=self.data['synapse']['single_exp_synapse']['exp_pair_wise_stdp_config_0']['hyperparameters'] + synapse_internal_state_A=self.data['synapse']['single_exp_synapse']['exp_pair_wise_stdp_config_0']['internal_state'] + learning_parameters_A=self.data['synapse']['single_exp_synapse']['exp_pair_wise_stdp_config_0']['learning_hyperparameters'] + internal_learning_state_A=self.data['synapse']['single_exp_synapse']['exp_pair_wise_stdp_config_0']['internal_learning_state'] + #LEARNING PARAMETERS B + synapse_parameters_B=self.data['synapse']['single_exp_synapse']['no_learning_config_0']['hyperparameters'] + synapse_internal_state_B=self.data['synapse']['single_exp_synapse']['no_learning_config_0']['internal_state'] + learning_parameters_B=self.data['synapse']['single_exp_synapse']['no_learning_config_0']['learning_hyperparameters'] + + # Create first external input synapse (stronger input) syn_ext_A = self._model.create_synapse( - breed="Single_Exp_Synapse", + breed="single_exp_synapse", pre_soma_id=np.nan, # External input (no pre-synaptic neuron) post_soma_id=soma_0, - parameters=synapse_parameters_A, - default_internal_state=synapse_internal_state, + config_name = 'exp_pair_wise_stdp_config_0', + hyperparameters_overrides=synapse_parameters_A, + default_internal_state_overrides=synapse_internal_state_A, + learning_hyperparameters_overrides=learning_parameters_A, + default_internal_learning_state_overrides=internal_learning_state_A ) # Create second external input synapse (weaker input) syn_ext_B = self._model.create_synapse( - breed="Single_Exp_Synapse", + breed="single_exp_synapse", pre_soma_id=np.nan, # External input (no pre-synaptic neuron) post_soma_id=soma_0, - parameters=synapse_parameters_B, - default_internal_state=synapse_internal_state, + config_name = 'exp_pair_wise_stdp_config_0', + hyperparameters_overrides=synapse_parameters_B, + default_internal_state_overrides=synapse_internal_state_B, + learning_hyperparameters_overrides=learning_parameters_B, + default_internal_learning_state_overrides=internal_learning_state_A ) # Create second external input synapse (weaker input) syn_int_C = self._model.create_synapse( - breed="Single_Exp_Synapse", + breed="single_exp_synapse", pre_soma_id=soma_0, # External input (no pre-synaptic neuron) post_soma_id=soma_1, - parameters=synapse_parameters_B, - default_internal_state=synapse_internal_state, + config_name = 'exp_pair_wise_stdp_config_0', + hyperparameters_overrides=synapse_parameters_B, + default_internal_state_overrides=synapse_internal_state_A, + learning_hyperparameters_overrides=learning_parameters_B, + default_internal_learning_state_overrides=internal_learning_state_A, ) # Initialize the simulation environment @@ -799,7 +654,7 @@ def test_dual_external_synapses_dual_somas(self): # Plot membrane potential plt.subplot(5, 1, 1) plt.plot(internal_states_history_soma0[:, 0], "b-", label="Soma 0") - plt.axhline(y=vthr, color="r", linestyle="--", label="Threshold") + plt.axhline(y=soma_parameters['vthr'], color="r", linestyle="--", label="Threshold") plt.ylabel("Membrane Pot. (mV)") plt.title("Soma 0") plt.legend() @@ -807,7 +662,7 @@ def test_dual_external_synapses_dual_somas(self): # Plot membrane potential plt.subplot(5, 1, 2) plt.plot(internal_states_history_soma1[:, 0], "b-", label="Soma 1") - plt.axhline(y=vthr, color="r", linestyle="--", label="Threshold") + plt.axhline(y=izh_soma_parameters['vthr'], color="r", linestyle="--", label="Threshold") plt.ylabel("Membrane Pot. (mV)") plt.title("Soma 1") plt.legend() @@ -885,39 +740,16 @@ def test_dual_external_synapses_dual_somas_STDP(self): self._model.register_global_property("dt", 1e-3) # Time step (100 μs) self._model.register_global_property("I_bias", 0) # No bias current - # Define LIF neuron parameters - C = 10e-9 # Membrane capacitance in Farads (10 nF) - R = 1e6 # Membrane resistance in Ohms (1 TΩ) - vthr = -45 # Spike threshold voltage (mV) - tref = 5e-3 # Refractory period (5 ms) - vrest = -60 # Resting potential (mV) - vreset = -70 # Reset potential after spike (mV) - tref_allows_integration = 1 # Allow integration during refractory period - I_in = 0 # No direct input current (only synaptic input) + soma_parameters = self.data['soma']['lif_soma']['config_0']['hyperparameters'] - # Package parameters for soma creation - soma_parameters_0 = [ - C, - R, - vthr, - tref, - vrest, - vreset, - tref_allows_integration, - I_in, - ] - - # Set initial internal state for neuron - v = vrest # Initial membrane voltage - tcount = 0 # Time counter - tlast = 0 # Last spike time - default_internal_state_0 = [v, tcount, tlast, 0] + default_internal_state = self.data['soma']['lif_soma']['config_0']['internal_state'] # Create single LIF neuron that will receive dual inputs soma_0 = self._model.create_soma( - breed="LIF_Soma", - parameters=soma_parameters_0, - default_internal_state=default_internal_state_0, + breed="lif_soma", + config_name='config_0', + hyperparameters_overrides=soma_parameters, + default_internal_state_overrides=default_internal_state, ) # # Create single LIF neuron that will receive dual inputs @@ -928,118 +760,61 @@ def test_dual_external_synapses_dual_somas_STDP(self): # ) # Create IZH soma - k = 1.2 - vthr = -45 - C = 150 - a = 0.01 - b = 5 - vpeak = 50 - vrest = -75 - d = 130 - vreset = -56 - I_in = 350 - soma_parameters_1 = [k, vthr, C, a, b, vpeak, vrest, d, vreset, I_in] - v = vrest - u = 0 - default_internal_state_1 = [v, u] + izh_soma_parameters = self.data['soma']['izh_soma']['config_0']['hyperparameters'] + izh_default_internal_state = self.data['soma']['izh_soma']['config_0']['internal_state'] + soma_1 = self._model.create_soma( - breed="IZH_Soma", - parameters=soma_parameters_1, - default_internal_state=default_internal_state_1, + breed="izh_soma", + config_name='config_0', + hyperparameters_overrides=izh_soma_parameters, + default_internal_state_overrides=izh_default_internal_state, ) + #LEARNING PARAMETERS A + synapse_parameters_A=self.data['synapse']['single_exp_synapse']['exp_pair_wise_stdp_config_0']['hyperparameters'] + synapse_internal_state_A=self.data['synapse']['single_exp_synapse']['exp_pair_wise_stdp_config_0']['internal_state'] + learning_parameters_A=self.data['synapse']['single_exp_synapse']['exp_pair_wise_stdp_config_0']['learning_hyperparameters'] + internal_learning_state_A=self.data['synapse']['single_exp_synapse']['exp_pair_wise_stdp_config_0']['internal_learning_state'] + #LEARNING PARAMETERS B + synapse_parameters_B=self.data['synapse']['single_exp_synapse']['no_learning_config_0']['hyperparameters'] + synapse_internal_state_B=self.data['synapse']['single_exp_synapse']['no_learning_config_0']['internal_state'] + learning_parameters_B=self.data['synapse']['single_exp_synapse']['no_learning_config_0']['learning_hyperparameters'] + - # Define synaptic parameters for first synapse (stronger weight) - weight_A = 2.0 # Stronger synaptic weight - synaptic_delay_A = 1.0 # Transmission delay (ms) - scale_A = 1.0 # Scaling factor - tau_fall_A = 1e-2 # Decay time constant (2 ms) - tau_rise_A = 0 # Rise time constant (instantaneous) - synapse_parameters_A = [ - weight_A, - synaptic_delay_A, - scale_A, - tau_fall_A, - tau_rise_A, - ] - - # Define synaptic parameters for second synapse (weaker weight) - weight_B = 1.0 # Weaker synaptic weight - synaptic_delay_B = 1.0 # Longer transmission delay (ms) - scale_B = 1.0 # Scaling factor - tau_fall_B = 1e-2 # Faster decay time constant (1 ms) - tau_rise_B = 0 # Rise time constant (instantaneous) - synapse_parameters_B = [ - weight_B, - synaptic_delay_B, - scale_B, - tau_fall_B, - tau_rise_B, - ] - - # Define STDP learning parameters - stdpType = 0 # Exp pair-wise STDP - tau_pre_stdp = 10e-3 # Pre-synaptic STDP time constant (10 ms) - tau_post_stdp = 10e-3 # Post-synaptic STDP time constant (10 ms) - a_exp_pre = 0.005 # Pre-synaptic STDP learning rate - a_exp_post = 0.005 # Post-synaptic STDP learning rate - stdp_history_length = 100 # Length of STDP history buffer - learning_parameters_A = [ - stdpType, - tau_pre_stdp, - tau_post_stdp, - a_exp_pre, - a_exp_post, - stdp_history_length, - ] - learning_parameters_B = [ - stdpType, # 0 - tau_pre_stdp, # 1 - tau_post_stdp, # 2 - a_exp_pre, # 3 - a_exp_post, # 4 - stdp_history_length, # 5 - ] - - # Internal learning state for STDP synapses - pre_trace = 0 - post_trace = 0 - dW = 0 - internal_learning_state_A = [pre_trace, post_trace, dW] - # Initial synaptic current for both synapses - I_synapse = 0.0 - synapse_internal_state = [I_synapse] # Create first external input synapse (stronger input) syn_ext_A = self._model.create_synapse( - breed="Single_Exp_Synapse", + breed="single_exp_synapse", pre_soma_id=np.nan, # External input (no pre-synaptic neuron) post_soma_id=soma_0, - parameters=synapse_parameters_A, - default_internal_state=synapse_internal_state, - learning_parameters=learning_parameters_A, - default_internal_learning_state=internal_learning_state_A, + config_name = 'exp_pair_wise_stdp_config_0', + hyperparameters_overrides=synapse_parameters_A, + default_internal_state_overrides=synapse_internal_state_A, + learning_hyperparameters_overrides=learning_parameters_A, + default_internal_learning_state_overrides=internal_learning_state_A ) # Create second external input synapse (weaker input) syn_ext_B = self._model.create_synapse( - breed="Single_Exp_Synapse", + breed="single_exp_synapse", pre_soma_id=np.nan, # External input (no pre-synaptic neuron) post_soma_id=soma_0, - parameters=synapse_parameters_B, - default_internal_state=synapse_internal_state, - learning_parameters=learning_parameters_B, - default_internal_learning_state=internal_learning_state_A, + config_name = 'exp_pair_wise_stdp_config_0', + hyperparameters_overrides=synapse_parameters_B, + default_internal_state_overrides=synapse_internal_state_B, + learning_hyperparameters_overrides=learning_parameters_B, + default_internal_learning_state_overrides=internal_learning_state_A ) # Create second external input synapse (weaker input) syn_int_C = self._model.create_synapse( - breed="Single_Exp_Synapse", + breed="single_exp_synapse", pre_soma_id=soma_0, # External input (no pre-synaptic neuron) post_soma_id=soma_1, - parameters=synapse_parameters_B, - default_internal_state=synapse_internal_state, - learning_parameters=learning_parameters_B, - default_internal_learning_state=internal_learning_state_A, + config_name = 'exp_pair_wise_stdp_config_0', + hyperparameters_overrides=synapse_parameters_B, + default_internal_state_overrides=synapse_internal_state_A, + learning_hyperparameters_overrides=learning_parameters_B, + default_internal_learning_state_overrides=internal_learning_state_A, ) # Initialize the simulation environment @@ -1114,7 +889,7 @@ def test_dual_external_synapses_dual_somas_STDP(self): # Plot membrane potential plt.subplot(12, 1, 1) plt.plot(internal_states_history_soma0[:, 0], "b-", label="Soma 0") - plt.axhline(y=vthr, color="r", linestyle="--", label="Threshold") + plt.axhline(y=soma_parameters['vthr'], color="r", linestyle="--", label="Threshold") plt.ylabel("Membrane Pot. (mV)") plt.title("Soma 0") plt.legend() @@ -1122,7 +897,7 @@ def test_dual_external_synapses_dual_somas_STDP(self): # Plot membrane potential plt.subplot(12, 1, 2) plt.plot(internal_states_history_soma1[:, 0], "b-", label="Soma 1") - plt.axhline(y=vthr, color="r", linestyle="--", label="Threshold") + plt.axhline(y=izh_soma_parameters['vthr'], color="r", linestyle="--", label="Threshold") plt.ylabel("Membrane Pot. (mV)") plt.title("Soma 1") plt.legend() From 886520995f6dc98112babc33e0d4a752bb6140d8 Mon Sep 17 00:00:00 2001 From: wfishell Date: Wed, 17 Sep 2025 17:29:12 +0000 Subject: [PATCH 3/3] committing the GCP instructions --- README_GCP.md | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 README_GCP.md diff --git a/README_GCP.md b/README_GCP.md new file mode 100644 index 0000000..4f73b13 --- /dev/null +++ b/README_GCP.md @@ -0,0 +1,76 @@ +# Installing Cupy for GCP Using NVIDIA GPU +* Make sure that there is enough space on your disk for your VM +### Install NVIDIA-Driver, any over 550 should work. This example used 570 + +```bash +sudo apt install nvidia-driver-570 +sudo reboot +``` +### Get CUDA runtime libraries +```bash +wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-ubuntu2204.pin +sudo mv cuda-ubuntu2204.pin /etc/apt/preferences.d/cuda-repository-pin-600 + +sudo apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/3bf863cc.pub + +sudo add-apt-repository -y "deb https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/ /" + +sudo apt-get update + +sudo apt-get -y install cuda + +sudo apt-get -y install libcudnn8 + +export PATH=/usr/local/cuda/bin:$PATH +export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH + +source ~/.bashrc + +nvcc --version +``` +### Install Conda using MiniConda +```bash +wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ~/miniconda.sh +bash ~/miniconda.sh -b -p $HOME/miniconda +#ADD TO PATH +echo 'export PATH=$HOME/miniconda/bin:$PATH' >> ~/.bashrc +source ~/.bashrc +``` +### Create an enviorment directory for your conda enviorment and enviorment +```bash +mkdir envs +cd envs +# MAKE ENV +conda create --prefix python=3.11.0 +source activate +``` +## Cupy installation instructions +Using nvidia-smi check your cuda version. Version tested with is 12.8 +Install cupy-cuda12x using pip; modify for cuda version<12 & >12 +```bash +python -m pip install --no-cache-dir cupy-cuda12x==13.6.0 +#check installation done correctly +python -c "import cupy; print(cupy.__file__)" +#run this as a test to make sure it works +python -c "import cupy as cp; x=cp.array([1,2,3]); print('Array test:', x*2)" +``` +### Install Superneuroabm +Clone repo and install dependencies +install mpi4py +```bash +sudo apt-get update +sudo apt-get install -y libopenmpi-dev openmpi-bin +pip install --no-cache-dir --force-reinstall mpi4py +``` +install all other dependencies +```bash +pip install sagesim==0.4.0dev1 +pip install networkx matplotlib pyyaml +pip install superneuroabm==1.0.0dev1 +``` +Now the unit tests can be run without error +Note at the time of this all functioning tests work off of the 62-update-and-expand-unit-tests +### running test +```bash +python -m unittest /tests/logic_gates_test_lif.py +``` \ No newline at end of file