Hi @galen
Here’s a merge of your code and the one I posted in the example. I give the connectivity matrix to Brian (it could also be a matrix of weights). The other option would be to generate the connectivity in Brian and then extract the connectivity/weight matrix – both approaches are described here: Synapses — Brian 2 2.5.1 documentation
I changed your plotting code slightly, since the Kuramoto model does not have not a binary activation but a continuous phase for each neuron:
# code to make an animation of node states over time and save as mp4
from matplotlib import pyplot as plt, animation
from matplotlib import colormaps
import networkx as nx
import numpy as np
from brian2 import *
defaultclock.dt = 1*ms
def run_sim(K, connection_matrix, runtime=10*second):
assert connection_matrix.ndim == 2, "need 2D matrix"
assert connection_matrix.shape[0] == connection_matrix.shape[1], "need quadratic matrix"
N = connection_matrix.shape[0]
eqs = '''
dTheta/dt = omega + K/N*coupling : radian
omega : radian/second (constant) # intrinsic frequency
coupling : 1
'''
oscillators = NeuronGroup(N, eqs, method='euler')
oscillators.Theta = 'rand()*2*pi' # random initial phase
oscillators.omega = 'clip(3 + randn()*1, 0, inf)*radian/second' # 𝒩(0.5, 0.5)
connections = Synapses(oscillators, oscillators,
'coupling_post = sin(Theta_pre - Theta_post) : 1 (summed)')
sources, targets = connection_matrix.nonzero()
connections.connect(i=sources, j=targets)
mon = StateMonitor(oscillators, 'Theta', record=True)
run(runtime)
return mon.Theta[:]
#%matplotlib inline
plt.rcParams["figure.autolayout"] = True
N = 10
#the number of possible states of each node
num_states_per_node = 2
A = np.random.randint(num_states_per_node, size = [N,N])
A = np.triu(A, k = 1)
# create the networkx graph
G = nx.from_numpy_array(A)
##### NOTE, pos (DICTIONARY OF NODE POSITIONS) COULD BE REPLACED WITH ACTUALLY NEURON LOCATIONS, IF KNOWN
pos = nx.spring_layout(G)
fig = plt.figure(figsize=[10,10])
node_states = np.random.randint(num_states_per_node, size = N)
nx.draw(G, node_color = node_states, edgecolors = 'grey', edge_color = 'lightgrey', cmap=colormaps['binary'])
# run simulation with given adjacency matrix
runtime = 10*second
results = run_sim(K=15/second, connection_matrix=A, runtime=runtime)
num_steps = 250
time_between_frames = runtime/num_steps
def animate(frame):
fig.clear()
time_step = int(round(frame*time_between_frames/defaultclock.dt))
node_states = results.T[time_step] % (2*pi)
nx.draw(G, pos, node_color = node_states, edgecolors = 'grey', edge_color = 'lightgrey', cmap=colormaps['twilight'], vmin=0, vmax=2*np.pi)
# create the animation
anim = animation.FuncAnimation(fig, animate, frames=num_steps, interval=time_between_frames/ms, repeat=False)
# saving to m4 using ffmpeg writer
writervideo = animation.FFMpegWriter(fps=25)
anim.save('percolation_zoom.mp4', writer=writervideo)
plt.close()
I increased the neurons’ intrinsic frequencies a bit, and made the connection quite strong so that one sees a clear phase synchronization between the units
:

PS: Discouse classifed your post as “potential spam” for some reason, so I had to manually accept to make it appear here for everyone.