def main(config): TAU_F = config['TAU_F'] W_FF = config['W_FF'] V_TH = config['V_TH'] G = config['G'] V_0 = config['V_0'] DS = config['DS'] FONT_SIZE = config['FONT_SIZE'] FIG_SIZE = config['FIG_SIZE'] def f(v, d): return (1 / TAU_F) * (-v + W_FF*phi(G*(v - V_TH)) + V_0 + d) vs = np.linspace(-6, 10, 200) fs = [f(vs, d) for d in DS] fig, ax = plt.subplots(1, 1, figsize=FIG_SIZE) ax.set_xlabel('v', fontsize=16) ax.set_ylabel('f(v)', fontsize=16) ax.plot(vs, np.transpose(fs), lw=2) ax.legend(['d = {}'.format(d) for d in DS], loc='best') ax.axvline(0, ls='--', lw=1, c='k') ax.axhline(0, ls='--', lw=1, c='k') axis_tools.set_fontsize(ax, FONT_SIZE)
def test3_input_populations_coupled_to_bistable_population(self): # define network drive drive_1 = 10*[0] + 20*[10] + 200*[0] drive_2 = 15*[0] + 20*[10] + 195*[0] drive_12 = len(drive_1) * [0] drives = np.transpose([drive_1, drive_2, drive_12]) # define network parameters taus = [10, 10, 10] v_rests = [0, 0, 0] v_ths = [4, 4, 4] gs = [2.5, 2.5, 2.5] noise_level = 2 nodes = [{'tau': t, 'v_rest': v_rest, 'threshold': th, 'steepness': g} for t, v_rest, th, g in zip(taus, v_rests, v_ths, gs)] weights = np.array([ [0, 0, 0], [0, 0, 0], [2, 2, 5.5] ]) # make network ntwk = RateBasedModel(nodes, weights) ntwk.store_voltages = True ntwk.noise_level = noise_level # initialize and run network np.random.seed(1) ntwk.vs = np.array(v_rests) for drive in drives: ntwk.step(drive) fig, axs = plt.subplots(3, 1, figsize=(14, 8), sharex=True) axs[0].plot(ntwk.vs_history, lw=2) axs[1].plot(ntwk.rs_history, lw=2) axs[2].plot(drives, lw=2) axs[1].set_ylim(-.1, 1.1) axs[2].set_ylim(-1, 11) axs[0].set_ylabel('voltage') axs[1].set_ylabel('firing rate') axs[2].set_ylabel('drive') axs[2].set_xlabel('t') axs[0].set_title('Input populations coupled to bistable population') for ax in axs: axis_tools.set_fontsize(ax, 20)
def test2_upstate_timecourse_with_self_connections_depends_on_noise(self): # define network drive drives = 10*[np.array([0, 0, 0])] + 40*[4*np.array([1, 1, 1])] + \ 140*[np.array([0, 0, 0])] # define network parameters taus = [10, 10, 10] v_rests = [0, 0, 0] v_ths = [4, 4, 4] gs = [2.5, 2.5, 2.5] w_selfs = [5.3, 5.3, 5.3] noise_level = np.array([1, 2, 3]) nodes = [{'tau': t, 'v_rest': v_rest, 'threshold': th, 'steepness': g} for t, v_rest, th, g in zip(taus, v_rests, v_ths, gs)] weights = np.diag(w_selfs) # make network ntwk = RateBasedModel(nodes, weights) ntwk.store_voltages = True ntwk.noise_level = noise_level # initialize and run network np.random.seed(seed=4) ntwk.vs = np.array(v_rests) for drive in drives: ntwk.step(drive) # make plots fig, axs = plt.subplots(3, 1, figsize=(14, 8), sharex=True) axs[0].plot(ntwk.vs_history, lw=2) axs[1].plot(ntwk.rs_history, lw=2) axs[2].plot(drives, lw=2, c='k') axs[1].set_ylim(-.1, 1.1) axs[2].set_ylim(-1, 5) axs[0].set_ylabel('voltage') axs[1].set_ylabel('firing rate') axs[2].set_ylabel('drive') axs[2].set_xlabel('t') axs[0].set_title('Self-Connected Populations With Noise') for ax in axs: axis_tools.set_fontsize(ax, 20)
def main(): # make network nodes = [{'tau': TAU, 'v_rest': v_rest, 'threshold': V_TH, 'steepness': G} for v_rest in V_RESTS] weights = np.array([ [0., 0, 0, 0, CWO], [0, 0, 0, CWO, 0], [FSW, FSW, SRW, 0, 0], [CWI, 0, CGW, 0, 0], [0, CWI, CGW, 0, 0], ]) ntwk = network.RateBasedModel(nodes, weights) ntwk.store_voltages = True ntwk.noise_level = NOISE_LEVEL # set up network drive drive_1 = 10*[0] + 20*[10] + 100*[0] + 20*[10] + 80*[0] drive_2 = 25*[0] + 20*[10] + 185*[0] drive_12s = len(drive_1) * [0] drive_12 = len(drive_1) * [0] drive_21 = len(drive_1) * [0] drives = np.transpose([drive_1, drive_2, drive_12s, drive_12, drive_21]) t = np.arange(len(drives)) # run network np.random.seed(SEED) ntwk.vs = np.array(V_RESTS) for drive in drives: ntwk.step(drive) # make figure fig, axs = plt.subplots(3, 1, facecolor=FACE_COLOR, figsize=FIG_SIZE, sharex=True) axs[0].plot(t, ntwk.vs_history, lw=2) axs[1].plot(t, ntwk.rs_history, lw=2) axs[2].plot(t, drives, lw=2) axs[0].set_ylabel('voltage') axs[1].set_ylabel('firing rate') axs[2].set_ylabel('drive') axs[2].set_xlabel('t') axs[0].set_title('Two-component memory network') for ax in axs: axis_tools.set_fontsize(ax, FONT_SIZE)
def test1_self_connections_yield_bistable_systems_given_correct_parameters(self): # define network drive drives = 10*[np.array([0, 0])] + 20*[4*np.array([1, 1])] + \ 60*[np.array([0, 0])] + 20*[-4*np.array([1, 1])] + 60*[np.array([0, 0])] # define network parameters taus = [10, 10] v_rests = [0, 0] v_ths = [4, 4] gs = [2.5, 2.5] w_selfs = [7.5, 5.5] nodes = [{'tau': t, 'v_rest': v_rest, 'threshold': th, 'steepness': g} for t, v_rest, th, g in zip(taus, v_rests, v_ths, gs)] weights = np.diag(w_selfs) # make network ntwk = RateBasedModel(nodes, weights) ntwk.store_voltages = True # initialize and run network ntwk.vs = np.array(v_rests) for drive in drives: ntwk.step(drive) # make plots fig, axs = plt.subplots(3, 1, figsize=(14, 8), sharex=True) axs[0].plot(ntwk.vs_history, lw=2) axs[1].plot(ntwk.rs_history, lw=2) axs[2].plot(drives, lw=2, c='k') axs[1].set_ylim(-.1, 1.1) axs[2].set_ylim(-5, 5) axs[0].set_ylabel('voltage') axs[1].set_ylabel('firing rate') axs[2].set_ylabel('drive') axs[2].set_xlabel('t') axs[0].set_title('Self-Connected Populations') for ax in axs: axis_tools.set_fontsize(ax, 20)
def test0_unconnected_populations_with_different_timescales_respond_to_delta_pulse_with_exponential_decay(self): # define network drive drives = 10*[np.array([0, 0, 0, 0])] + 10*[2*np.array([3, 4, 6, 10])] + 60*[np.array([0, 0, 0, 0])] # define network parameters taus = [3, 5, 10, 20] v_rests = [-20, -10, 0, 10] v_ths = [-10, -1, 8, 17] gs = [.5, .5, .5, .5] # dake new network nodes = [{'tau': t, 'v_rest': v_rest, 'threshold': th, 'steepness': g} for t, v_rest, th, g in zip(taus, v_rests, v_ths, gs)] weights = np.zeros((len(taus), len(taus))) ntwk = RateBasedModel(nodes, weights) ntwk.store_voltages = True # initialize and run network ntwk.vs = np.array(v_rests) for drive in drives: ntwk.step(drive) # make plots fig, axs = plt.subplots(3, 1, figsize=(14, 8), sharex=True) axs[0].plot(ntwk.vs_history, lw=2) axs[1].plot(ntwk.rs_history, lw=2) axs[2].plot(drives, lw=2) axs[1].set_ylim(-.1, 1.1) axs[2].set_ylim(0, 45) axs[0].set_ylabel('voltage') axs[1].set_ylabel('firing rate') axs[2].set_ylabel('drive') axs[2].set_xlabel('t') axs[0].set_title('Uncoupled Populations') for ax in axs: axis_tools.set_fontsize(ax, 20)
def novel_pattern_learning(CONFIG): """ Show that a network has an increased probability of embedding a novel pattern into its connectivity network if we allow nonassociative priming to act. """ SEED = CONFIG["SEED"] LOAD_FILE_NAME = CONFIG["LOAD_FILE_NAME"] W_WEAK = CONFIG["W_WEAK"] GAIN = CONFIG["GAIN"] REFRACTORY_STRENGTH = CONFIG["REFRACTORY_STRENGTH"] LINGERING_INPUT_VALUE = CONFIG["LINGERING_INPUT_VALUE"] LINGERING_INPUT_TIMESCALE = CONFIG["LINGERING_INPUT_TIMESCALE"] W_MAX = CONFIG["W_MAX"] ALPHA = CONFIG["ALPHA"] STRONG_DRIVE_AMPLITUDE = CONFIG["STRONG_DRIVE_AMPLITUDE"] RUN_LENGTH = CONFIG["RUN_LENGTH"] N_REPEATS = CONFIG["N_REPEATS"] FIG_SIZE_0 = CONFIG["FIG_SIZE_0"] FONT_SIZE = CONFIG["FONT_SIZE"] np.random.seed(SEED) # create new network with STDP learning rule ntwk_old = np.load(LOAD_FILE_NAME)[0] w = ntwk_old.w.copy() # add weak connection to element 2 of node_1 path tree from element 1 of node_0 path tree w[ntwk_old.node_1_path_tree[0][2], ntwk_old.node_0_path_tree[0][1]] = W_WEAK w_to_track = (ntwk_old.node_1_path_tree[0][2], ntwk_old.node_0_path_tree[0][1]) path_novel = ntwk_old.node_0_path_tree[0][:2] + ntwk_old.node_1_path_tree[0][2:] # make new base network ntwk_base = network.RecurrentSoftMaxLingeringSTDPModelBasic( w, GAIN, REFRACTORY_STRENGTH, LINGERING_INPUT_VALUE, LINGERING_INPUT_TIMESCALE, W_MAX, ALPHA ) ntwk_base.node_0 = ntwk_old.node_0 ntwk_base.node_0 = ntwk_old.node_1 ntwk_base.node_0_path_tree = ntwk_old.node_0_path_tree ntwk_base.node_1_path_tree = ntwk_old.node_1_path_tree # show long trials of novel sequence drive, spontaneous activity, and test sequence fig, axs = plt.subplots(N_REPEATS, 1, figsize=FIG_SIZE_0, sharex=True, tight_layout=True) axs_twin = [ax.twinx() for ax in axs] drives = np.zeros((RUN_LENGTH, ntwk_base.w.shape[0]), dtype=float) for ctr, node in enumerate(path_novel): drives[ctr, node] = STRONG_DRIVE_AMPLITUDE for ax, ax_twin in zip(axs, axs_twin): ntwk = deepcopy(ntwk_base) ntwk.store_voltages = True ws = [] for drive in drives: ntwk.step(drive) ws.append(ntwk.w[w_to_track]) spikes = np.array(ntwk.rs_history) fancy_raster.by_row_circles(ax, spikes, drives) ax_twin.plot(ws, color="b", lw=2, alpha=0.7) ax.set_ylabel("active \n ensemble") ax_twin.set_ylabel("W({}, {})".format(*w_to_track), color="b") axs[-1].set_xlabel("time step") for ax_twin in axs_twin: ax_twin.set_ylim(0, 2) axs[0].set_xlim(-5, RUN_LENGTH) axs[0].set_title("With nonassociative priming") for ax in list(axs) + axs_twin: axis_tools.set_fontsize(ax, FONT_SIZE) fig, axs = plt.subplots(N_REPEATS, 1, figsize=FIG_SIZE_0, sharex=True, tight_layout=True) axs_twin = [ax.twinx() for ax in axs] drives = np.zeros((RUN_LENGTH, ntwk_base.w.shape[0]), dtype=float) for ctr, node in enumerate(path_novel): drives[ctr, node] = STRONG_DRIVE_AMPLITUDE for ax, ax_twin in zip(axs, axs_twin): ntwk = deepcopy(ntwk_base) ntwk.lingering_input_value = 0 ntwk.store_voltages = True ws = [] for drive in drives: ntwk.step(drive) ws.append(ntwk.w[w_to_track]) spikes = np.array(ntwk.rs_history) fancy_raster.by_row_circles(ax, spikes, drives) ax_twin.plot(ws, color="b", lw=2, alpha=0.7) ax.set_ylabel("active \n ensemble") ax_twin.set_ylabel("W({}, {})".format(*w_to_track), color="b") axs[-1].set_xlabel("time step") for ax_twin in axs_twin: ax_twin.set_ylim(0, 2) axs[0].set_xlim(-5, RUN_LENGTH) axs[0].set_title("Without nonassociative priming") for ax in list(axs) + axs_twin: axis_tools.set_fontsize(ax, FONT_SIZE)
def main(config): SEED = config['SEED'] TAU_E = config['TAU_E'] TAU_I = config['TAU_I'] V_REST_E = config['V_REST_E'] V_REST_I = config['V_REST_I'] V_TH = config['V_TH'] STEEPNESS = config['STEEPNESS'] W_EE = config['W_EE'] W_EI = config['W_EI'] W_IE = config['W_IE'] NOISE_LEVEL = config['NOISE_LEVEL'] DRIVE_AMPS = config['DRIVE_AMPS'] DRIVE_STARTS = config['DRIVE_STARTS'] DRIVE_ENDS = config['DRIVE_ENDS'] DURATION = config['DURATION'] FIG_SIZE = config['FIG_SIZE'] FONT_SIZE = config['FONT_SIZE'] COLOR_CYCLE = config['COLOR_CYCLE'] # set up nodes and weights nodes = [ {'tau': TAU_E, 'v_rest': V_REST_E, 'threshold': V_TH, 'steepness': STEEPNESS,}, {'tau': TAU_I, 'v_rest': V_REST_I, 'threshold': V_TH, 'steepness': STEEPNESS,}, ] weights = np.array([ [W_EE, W_EI], [W_IE, 0.0], ]) # build network ntwk = network.RateBasedModel(nodes, weights) ntwk.store_voltages = True ntwk.noise_level = NOISE_LEVEL # set up drive drives = np.zeros((DURATION, len(nodes)), dtype=float) for drive_amp, drive_start, drive_end in zip(DRIVE_AMPS, DRIVE_STARTS, DRIVE_ENDS): drives[drive_start:drive_end, 0] = drive_amp # run network np.random.seed(SEED) ntwk.vs = np.array([V_REST_E, V_REST_I]) for drive in drives: ntwk.step(drive) # make figure fig, axs = plt.subplots(3, 1, figsize=FIG_SIZE, sharex=True, tight_layout=True) axs_twin = [ax.twinx() for ax in axs[:2]] axs[0].plot(np.array(ntwk.vs_history)[:, 0], c=COLOR_CYCLE[0], ls='--', lw=2) axs_twin[0].plot(np.array(ntwk.rs_history)[:, 0], c=COLOR_CYCLE[0], ls='-', lw=2) axs[1].plot(np.array(ntwk.vs_history)[:, 1], c=COLOR_CYCLE[1], ls='--', lw=2) axs_twin[1].plot(np.array(ntwk.rs_history)[:, 1], c=COLOR_CYCLE[1], ls='-', lw=2) axs[2].set_color_cycle(COLOR_CYCLE) axs[2].plot(drives, lw=2) axs_twin[0].set_ylim(0, 1) axs_twin[1].set_ylim(0, 1) axs[2].set_ylim(0, drives.max() * 1.1) axs[0].set_title('Excitatory') axs[0].set_ylabel('Voltage') axs_twin[0].set_ylabel('Firing rate') axs[1].set_title('Inhibitory') axs[1].set_ylabel('Voltage') axs_twin[1].set_ylabel('Firing rate') axs[2].set_title('Drive') axs[2].set_ylabel('Drive') axs[2].set_xlabel('t') for ax in list(axs) + list(axs_twin): axis_tools.set_fontsize(ax, FONT_SIZE)
def main(config): # unpack params from config SEED = config['SEED'] TAU_I = config['TAU_I'] TAU_R = config['TAU_R'] TAU_B = config['TAU_B'] TAU_A = config['TAU_A'] V_REST_I = config['V_REST_I'] V_REST_R = config['V_REST_R'] V_REST_B = config['V_REST_B'] V_REST_A = config['V_REST_A'] STEEPNESS = config['STEEPNESS'] THRESHOLD = config['THRESHOLD'] W_IB = config['W_IB'] W_BI = config['W_BI'] W_BR = config['W_BR'] W_AB = config['W_AB'] W_AA = config['W_AA'] NOISE_LEVEL = config['NOISE_LEVEL'] DURATION = config['DURATION'] DRIVE_11_START = config['DRIVE_11_START'] DRIVE_11_END = config['DRIVE_11_END'] DRIVE_11_AMP = config['DRIVE_11_AMP'] DRIVE_12_START = config['DRIVE_12_START'] DRIVE_12_END = config['DRIVE_12_END'] DRIVE_12_AMP = config['DRIVE_12_AMP'] DRIVE_13_START = config['DRIVE_13_START'] DRIVE_13_END = config['DRIVE_13_END'] DRIVE_13_AMP = config['DRIVE_13_AMP'] DRIVE_21_START = config['DRIVE_21_START'] DRIVE_21_END = config['DRIVE_21_END'] DRIVE_21_AMP = config['DRIVE_21_AMP'] COLOR_CYCLE = config['COLOR_CYCLE'] FIG_SIZE = config['FIG_SIZE'] FONT_SIZE = config['FONT_SIZE'] # set up nodes # order: (I, R1, R2, R3, R4, B12, B13, B14, B23, B24, B34, A12, A13, A14, A23, A24, A34) nodes = [ {'tau': TAU_I, 'v_rest': V_REST_I, 'threshold': THRESHOLD, 'steepness': STEEPNESS}, # I {'tau': TAU_R, 'v_rest': V_REST_R, 'threshold': THRESHOLD, 'steepness': STEEPNESS}, # R1 {'tau': TAU_R, 'v_rest': V_REST_R, 'threshold': THRESHOLD, 'steepness': STEEPNESS}, # R2 {'tau': TAU_R, 'v_rest': V_REST_R, 'threshold': THRESHOLD, 'steepness': STEEPNESS}, # R3 {'tau': TAU_R, 'v_rest': V_REST_R, 'threshold': THRESHOLD, 'steepness': STEEPNESS}, # R4 {'tau': TAU_B, 'v_rest': V_REST_B, 'threshold': THRESHOLD, 'steepness': STEEPNESS}, # B12 {'tau': TAU_B, 'v_rest': V_REST_B, 'threshold': THRESHOLD, 'steepness': STEEPNESS}, # B13 {'tau': TAU_B, 'v_rest': V_REST_B, 'threshold': THRESHOLD, 'steepness': STEEPNESS}, # B14 {'tau': TAU_B, 'v_rest': V_REST_B, 'threshold': THRESHOLD, 'steepness': STEEPNESS}, # B23 {'tau': TAU_B, 'v_rest': V_REST_B, 'threshold': THRESHOLD, 'steepness': STEEPNESS}, # B24 {'tau': TAU_B, 'v_rest': V_REST_B, 'threshold': THRESHOLD, 'steepness': STEEPNESS}, # B34 {'tau': TAU_A, 'v_rest': V_REST_A, 'threshold': THRESHOLD, 'steepness': STEEPNESS}, # A12 {'tau': TAU_A, 'v_rest': V_REST_A, 'threshold': THRESHOLD, 'steepness': STEEPNESS}, # A13 {'tau': TAU_A, 'v_rest': V_REST_A, 'threshold': THRESHOLD, 'steepness': STEEPNESS}, # A14 {'tau': TAU_A, 'v_rest': V_REST_A, 'threshold': THRESHOLD, 'steepness': STEEPNESS}, # A23 {'tau': TAU_A, 'v_rest': V_REST_A, 'threshold': THRESHOLD, 'steepness': STEEPNESS}, # A24 {'tau': TAU_A, 'v_rest': V_REST_A, 'threshold': THRESHOLD, 'steepness': STEEPNESS}, # A34 ] # set up weight matrix weights = np.array([ # I R1 R2 R3 R4 B12 B13 B14 B23 B24 B34 A12 A13 A14 A23 A24 A34 [ 0.0, 0.0, 0.0, 0.0, 0.0, W_IB, W_IB, W_IB, W_IB, W_IB, W_IB, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,], # I [ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,], # R1 [ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,], # R2 [ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,], # R3 [ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,], # R4 [W_BI, W_BR, W_BR, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,], # B12 [W_BI, W_BR, 0.0, W_BR, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,], # B13 [W_BI, W_BR, 0.0, 0.0, W_BR, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,], # B14 [W_BI, 0.0, W_BR, W_BR, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,], # B23 [W_BI, 0.0, W_BR, 0.0, W_BR, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,], # B24 [W_BI, 0.0, 0.0, W_BR, W_BR, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,], # B34 [ 0.0, 0.0, 0.0, 0.0, 0.0, W_AB, 0.0, 0.0, 0.0, 0.0, 0.0, W_AA, 0.0, 0.0, 0.0, 0.0, 0.0,], # A12 [ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, W_AB, 0.0, 0.0, 0.0, 0.0, 0.0, W_AA, 0.0, 0.0, 0.0, 0.0,], # A13 [ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, W_AB, 0.0, 0.0, 0.0, 0.0, 0.0, W_AA, 0.0, 0.0, 0.0,], # A14 [ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, W_AB, 0.0, 0.0, 0.0, 0.0, 0.0, W_AA, 0.0, 0.0,], # A23 [ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, W_AB, 0.0, 0.0, 0.0, 0.0, 0.0, W_AA, 0.0,], # A24 [ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, W_AB, 0.0, 0.0, 0.0, 0.0, 0.0, W_AA,], # A34 # I R1 R2 R3 R4 B12 B13 B14 B23 B24 B34 A12 A13 A14 A23 A24 A34 ]) # build network ntwk = network.RateBasedModel(nodes, weights) ntwk.store_voltages = True ntwk.noise_level = NOISE_LEVEL # set up drive drives = np.zeros((DURATION, len(nodes)), dtype=float) drives[DRIVE_11_START:DRIVE_11_END, 1] = DRIVE_11_AMP drives[DRIVE_12_START:DRIVE_12_END, 1] = DRIVE_12_AMP drives[DRIVE_13_START:DRIVE_13_END, 1] = DRIVE_13_AMP drives[DRIVE_21_START:DRIVE_21_END, 2] = DRIVE_21_AMP # run network np.random.seed(SEED) ntwk.vs = np.array([node['v_rest'] for node in nodes]) for drive in drives: ntwk.step(drive) # open a figure fig, axs = plt.subplots(4, 1, figsize=FIG_SIZE, sharex=True, tight_layout=True) axs_twinx = [None] + [ax.twinx() for ax in axs[1:]] # plot drive axs[0].set_color_cycle(COLOR_CYCLE) axs[0].plot(drives[:, 1:5], lw=2) # plot responses of receptive field (R) units axs[1].set_color_cycle(COLOR_CYCLE) axs_twinx[1].set_color_cycle(COLOR_CYCLE) axs[1].plot(np.array(ntwk.vs_history)[:, 1:5], ls='--', lw=2) axs_twinx[1].plot(np.array(ntwk.rs_history)[:, 1:5], ls='-', lw=2) # plot responses of buffer (B) units axs[2].set_color_cycle(COLOR_CYCLE[4:]) axs_twinx[2].set_color_cycle(COLOR_CYCLE[4:]) axs[2].plot(np.array(ntwk.vs_history)[:, 5:11], ls='--', lw=2) axs_twinx[2].plot(np.array(ntwk.rs_history)[:,5:11], ls='-', lw=2) # plot response of inhibitory (I) unit axs[2].plot(np.array(ntwk.vs_history)[:, 0], ls='--', lw=2, color='k') axs_twinx[2].plot(np.array(ntwk.rs_history)[:, 0], ls='-', lw=2, color='k') # plot response of association (A) units axs[3].set_color_cycle(COLOR_CYCLE[4:]) axs_twinx[3].set_color_cycle(COLOR_CYCLE[4:]) axs[3].plot(np.array(ntwk.vs_history)[:, 11:], ls='--', lw=2) axs_twinx[3].plot(np.array(ntwk.rs_history)[:, 11:], ls='-', lw=2) # set axis limits for ax in axs_twinx[1:]: ax.set_ylim(0, 1) # label things axs[0].set_title('drive') axs[0].set_ylabel('strength') axs[1].set_title('receptive field units') axs[1].set_ylabel('voltage') axs_twinx[1].set_ylabel('firing rate') axs[2].set_title('buffer units') axs[2].set_ylabel('voltage') axs_twinx[2].set_ylabel('firing rate') axs[3].set_title('association units') axs[3].set_ylabel('voltage') axs_twinx[3].set_ylabel('firing rate') axs[3].set_xlabel('time') for ax in list(axs) + axs_twinx[1:]: axis_tools.set_fontsize(ax, FONT_SIZE)
def main(config): # unpack params from config SEED = config['SEED'] TAU = config['TAU'] TAU_M = config['TAU_M'] TAU_C = config['TAU_C'] V_REST = config['V_REST'] V_REST_C = config['V_REST_C'] V_TH = config['V_TH'] STEEPNESS = config['STEEPNESS'] W_IF = config['W_IF'] W_FS = config['W_FS'] W_FI = config['W_FI'] W_FF = config['W_FF'] W_FC = config['W_FC'] W_MF = config['W_MF'] W_MM = config['W_MM'] W_CF = config['W_CF'] W_CM = config['W_CM'] N_UNITS = config['N_UNITS'] NOISE_LEVEL = config['NOISE_LEVEL'] S_DRIVE_AMP = config['S_DRIVE_AMP'] F0_DRIVE_AMP = config['F0_DRIVE_AMP'] F1_DRIVE_AMP = config['F1_DRIVE_AMP'] T_F0_DRIVE = config['T_F0_DRIVE'] D_F0_DRIVE = config['D_F0_DRIVE'] T_F1_DRIVE = config['T_F1_DRIVE'] D_F1_DRIVE = config['D_F1_DRIVE'] T2_F1_DRIVE = config['T2_F1_DRIVE'] D2_F1_DRIVE = config['D2_F1_DRIVE'] T2_F0_DRIVE = config['T2_F0_DRIVE'] D2_F0_DRIVE = config['D2_F0_DRIVE'] T_S_DRIVE = config['T_S_DRIVE'] DURATION = config['DURATION'] FONT_SIZE = config['FONT_SIZE'] COLOR_CYCLE = config['COLOR_CYCLE'] # generate network nodes and weights using helper function nodes, weights = network_param_gen.wta_memory_combo( n_units=N_UNITS, tau=TAU, tau_m=TAU_M, tau_c=TAU_C, v_rest=V_REST, v_rest_c=V_REST_C, v_th=V_TH, steepness=STEEPNESS, w_if=W_IF, w_fs=W_FS, w_fi=W_FI, w_ff=W_FF, w_fc=W_FC, w_mf=W_MF, w_mm=W_MM, w_cf=W_CF, w_cm=W_CM, ) # the order of the neurons in this network is: # s, i, f, f, ..., f, f, m, c, c, m, c, c, ..., m, c, c, m, c, c # there are N_UNITS f neurons, and N_UNITS*(N_UNITS-1)/2 m, c, c groups ntwk = network.RateBasedModel(nodes, weights) ntwk.noise_level = NOISE_LEVEL ntwk.store_voltages = True # setup network drive s_drive = np.zeros((DURATION, 1), dtype=float) s_drive[T_S_DRIVE:, 0] = S_DRIVE_AMP f_drive = np.zeros((DURATION, N_UNITS), dtype=float) f_drive[T_F0_DRIVE:T_F0_DRIVE+D_F0_DRIVE, 0] = F0_DRIVE_AMP f_drive[T_F1_DRIVE:T_F1_DRIVE+D_F1_DRIVE, 1] = F1_DRIVE_AMP f_drive[T2_F1_DRIVE:T2_F1_DRIVE+D2_F1_DRIVE, 1] = F1_DRIVE_AMP f_drive[T2_F0_DRIVE:T2_F0_DRIVE+D2_F0_DRIVE, 0] = F0_DRIVE_AMP i_drive = np.zeros((DURATION, 1), dtype=float) mcc_drive = np.zeros((DURATION, 3*N_UNITS*(N_UNITS-1)/2), dtype=float) drives = np.concatenate([s_drive, i_drive, f_drive, mcc_drive], axis=1) # run simulation np.random.seed(SEED) ntwk.vs = np.array([n['v_rest'] for n in nodes]) for drive in drives: ntwk.step(drive) # do some things before making figures rs = np.array(ntwk.rs_history) vs = np.array(ntwk.vs_history) f_idxs = np.arange(2, 2 + N_UNITS, dtype=int) m_idxs = np.arange(2 + N_UNITS, 2 + N_UNITS + 3 * N_UNITS * (N_UNITS - 1) / 2, 3, dtype=int) fig, axs = plt.subplots(4, 1, figsize=(15, 12), sharex=True, tight_layout=True) axs[3].twin = axs[3].twinx() for ax in np.concatenate([axs.flatten(), [axs[3].twin]]): ax.set_color_cycle(COLOR_CYCLE) axs[0].plot(rs[:, f_idxs], lw=2) axs[1].plot(drives[:, np.concatenate([f_idxs, [0]])], lw=2) axs[2].plot(vs[:, m_idxs], lw=2) axs[3].plot(rs[:, range(m_idxs[0] + 1, m_idxs[0] + 3)], lw=2, ls='-') axs[3].twin.plot(vs[:, range(m_idxs[0] + 1, m_idxs[0] + 3)], lw=2, ls='--') axs[0].set_title('Fast units') axs[0].set_ylabel('Firing rate') axs[1].set_title('Drive') axs[1].set_ylabel('Drive') axs[2].set_title('Memory units') axs[2].set_ylabel('Voltage') axs[3].set_title('Conduit units') axs[3].set_ylabel('Firing rate') axs[3].twin.set_ylabel('Voltage') axs[3].set_xlabel('t') for ax in np.concatenate([axs.flatten(), [axs[3].twin]]): axis_tools.set_fontsize(ax, FONT_SIZE)
def novel_pattern_replay(CONFIG): """ Show how a network that has weak connections in addition to its strong connections can learn to replay novel patterns that would not normally arise spontaneously. """ SEED = CONFIG['SEED'] LOAD_FILE_NAME = CONFIG['LOAD_FILE_NAME'] W_WEAK = CONFIG['W_WEAK'] GAIN = CONFIG['GAIN'] REFRACTORY_STRENGTH = CONFIG['REFRACTORY_STRENGTH'] LINGERING_INPUT_VALUE = CONFIG['LINGERING_INPUT_VALUE'] LINGERING_INPUT_TIMESCALE = CONFIG['LINGERING_INPUT_TIMESCALE'] STRONG_DRIVE_AMPLITUDE = CONFIG['STRONG_DRIVE_AMPLITUDE'] WEAK_DRIVE_AMPLITUDE = CONFIG['WEAK_DRIVE_AMPLITUDE'] TRIAL_LENGTH_TRIGGERED_REPLAY = CONFIG['TRIAL_LENGTH_TRIGGERED_REPLAY'] RUN_LENGTH = CONFIG['RUN_LENGTH'] FIG_SIZE_0 = CONFIG['FIG_SIZE_0'] FIG_SIZE_1 = CONFIG['FIG_SIZE_1'] FONT_SIZE = CONFIG['FONT_SIZE'] np.random.seed(SEED) fig = plt.figure(figsize=FIG_SIZE_0, tight_layout=True) axs = [] for row_ctr in range(3): axs.append([fig.add_subplot(4, 3, 3*row_ctr + col_ctr) for col_ctr in range(1, 4)]) axs = list(axs) axs.append(fig.add_subplot(4, 1, 4)) # load old network ntwk_old = np.load(LOAD_FILE_NAME)[0] # demonstrate how one cannot use intrinsic plasticity to learn sequence that is made of disjoint paths path = list(ntwk_old.node_0_path_tree[0][:]) path[2:] = ntwk_old.node_1_path_tree[0][2:] drives = np.zeros((TRIAL_LENGTH_TRIGGERED_REPLAY, ntwk_old.w.shape[0]), dtype=float) for ctr, node in enumerate(path): drives[ctr, node] = STRONG_DRIVE_AMPLITUDE drives[len(path), path[0]] = STRONG_DRIVE_AMPLITUDE for ctr, ax in enumerate(axs[0]): ntwk = deepcopy(ntwk_old) ntwk.store_voltages = True for drive in drives: ntwk.step(drive) spikes = np.array(ntwk.rs_history) fancy_raster.by_row_circles(ax, spikes, drives) ax.set_xlim(-1, len(drives)) ax.set_ylim(-1, 20) ax.set_xlabel('time step') ax.set_ylabel('active \n ensemble') ax.set_title('Strongly driving nonexisting path (trial {})'.format(ctr + 1)) w = ntwk_old.w.copy() # add weak connection to element 2 of node_1 path tree from element 1 of node_0 path tree w[ntwk_old.node_1_path_tree[0][2], ntwk_old.node_0_path_tree[0][1]] = W_WEAK # make new base network ntwk_base = network.RecurrentSoftMaxLingeringModel( w, GAIN, REFRACTORY_STRENGTH, LINGERING_INPUT_VALUE, LINGERING_INPUT_TIMESCALE ) ntwk_base.node_0 = ntwk_old.node_0 ntwk_base.node_0 = ntwk_old.node_1 ntwk_base.node_0_path_tree = ntwk_old.node_0_path_tree ntwk_base.node_1_path_tree = ntwk_old.node_1_path_tree # demonstrate how weak connections allow linking of paths into short term memory path = list(ntwk_base.node_0_path_tree[0][:]) path[2:] = ntwk_base.node_1_path_tree[0][2:] drives = np.zeros((TRIAL_LENGTH_TRIGGERED_REPLAY, ntwk_base.w.shape[0]), dtype=float) for ctr, node in enumerate(path): drives[ctr, node] = STRONG_DRIVE_AMPLITUDE drives[len(path), path[0]] = STRONG_DRIVE_AMPLITUDE for ctr, ax in enumerate(axs[1]): ntwk = deepcopy(ntwk_base) ntwk.store_voltages = True for drive in drives: ntwk.step(drive) spikes = np.array(ntwk.rs_history) fancy_raster.by_row_circles(ax, spikes, drives) ax.set_xlim(-1, len(drives)) ax.set_ylim(-1, 20) ax.set_xlabel('time step') ax.set_ylabel('active \n ensemble') ax.set_title('Activity from forced initial condition after \n driving path with weak connection (trial {})'.format(ctr + 1)) # demonstrate how weak connections do not substantially affect path probabilities path = list(ntwk_base.node_0_path_tree[0][:]) path[2:] = ntwk_base.node_1_path_tree[0][2:] drives = np.zeros((TRIAL_LENGTH_TRIGGERED_REPLAY, ntwk_old.w.shape[0]), dtype=float) drives[0, path[0]] = STRONG_DRIVE_AMPLITUDE for ctr, ax in enumerate(axs[2]): ntwk = deepcopy(ntwk_base) ntwk.store_voltages = True for drive in drives: ntwk.step(drive) spikes = np.array(ntwk.rs_history) fancy_raster.by_row_circles(ax, spikes, drives) ax.set_xlim(-1, len(drives)) ax.set_ylim(-1, 20) ax.set_xlabel('time step') ax.set_ylabel('active ensemble') ax.set_title('Free activity after only forcing \n initial condition (trial {})'.format(ctr + 1)) path = list(ntwk_base.node_0_path_tree[0][:]) path[2:] = ntwk_base.node_1_path_tree[0][2:] drives = np.zeros((RUN_LENGTH, ntwk_base.w.shape[0]), dtype=float) for ctr, node in enumerate(path): drives[ctr, node] = STRONG_DRIVE_AMPLITUDE ntwk = deepcopy(ntwk_base) ntwk.store_voltages = True for drive in drives: ntwk.step(drive) spikes = np.array(ntwk.rs_history) fancy_raster.by_row_circles(axs[3], spikes, drives) axs[3].set_xlim(-1, len(drives)) axs[3].set_ylim(-1, 40) axs[3].set_xlabel('time step') axs[3].set_ylabel('active \n ensemble') axs[3].set_title('Free activity after driving path with weak connection') for ax_row in axs[:-1]: for ax in ax_row: axis_tools.set_fontsize(ax, FONT_SIZE) axis_tools.set_fontsize(axs[-1], FONT_SIZE) # now demonstrate how pattern-matching computation changes with respect to short-term memory fig, axs = plt.subplots(1, 2, figsize=FIG_SIZE_1, tight_layout=True) path = list(ntwk_base.node_0_path_tree[1][:]) path[0] = 22 path[2] = 17 path[3] = ntwk_base.node_1_path_tree[0][3] drives_new = np.zeros((len(path), ntwk_base.w.shape[0]), dtype=float) drives_new[0, path[0]] = STRONG_DRIVE_AMPLITUDE for ctr, node in enumerate(path[1:]): drives_new[ctr + 1, node] = WEAK_DRIVE_AMPLITUDE # drive a network with just the new drive to see how it completes the pattern ntwk = deepcopy(ntwk_base) ntwk.store_voltages = True for drive in drives_new: ntwk.step(drive) spikes = np.array(ntwk.rs_history) fancy_raster.by_row_circles(axs[0], spikes, drives_new) axs[0].set_xlim(-1, 8) axs[0].set_ylim(-1, ntwk_base.w.shape[0]) axs[0].set_xlabel('time step') axs[0].set_ylabel('active ensemble') axs[0].set_title('Weakly driving nonexistent path') drives = np.concatenate([drives[:4, :], drives_new]) ntwk = deepcopy(ntwk_base) ntwk.store_voltages = True for drive in drives: ntwk.step(drive) spikes = np.array(ntwk.rs_history) fancy_raster.by_row_circles(axs[1], spikes, drives) axs[1].set_xlim(-1, 8) axs[1].set_ylim(-1, ntwk_base.w.shape[0]) axs[1].set_xlabel('time step') axs[1].set_ylabel('active ensemble') axs[1].set_title('Weakly driving nonexistent path after \n strongly driving path with weak connection') for ax in axs: axis_tools.set_fontsize(ax, FONT_SIZE)
def basic_replay_stats(CONFIG): """ Plot some statistics of this network's behavior. """ SEED = CONFIG['SEED'] LOAD_FILE_NAME = CONFIG['LOAD_FILE_NAME'] GAIN_HIGH = CONFIG['GAIN_HIGH'] GAIN_LOW = CONFIG['GAIN_LOW'] LINGERING_INPUT_VALUE = CONFIG['LINGERING_INPUT_VALUE'] LINGERING_INPUT_TIMESCALE = CONFIG['LINGERING_INPUT_TIMESCALE'] STRONG_DRIVE_AMPLITUDE = CONFIG['STRONG_DRIVE_AMPLITUDE'] T_SPONTANEOUS = CONFIG['T_SPONTANEOUS'] SPONTANEOUS_REPEATS = CONFIG['SPONTANEOUS_REPEATS'] FIG_SIZE = CONFIG['FIG_SIZE'] FONT_SIZE = CONFIG['FONT_SIZE'] np.random.seed(SEED) fig, axs = plt.subplots(1, 3, figsize=FIG_SIZE, tight_layout=True) ntwk_base = np.load(LOAD_FILE_NAME)[0] n_nodes = ntwk_base.w.shape[0] # show that adding in lingering activity increases probability of replay driven_path = ntwk_base.node_0_path_tree[0] p_replay_no_lingering = 1 for node_prev, node_next in zip(driven_path[:-1], driven_path[1:]): intrinsic = ntwk_base.w[:, node_prev] refractory = np.zeros((n_nodes,), dtype=float) refractory[node_prev] = ntwk_base.refractory_strength inputs = intrinsic + refractory prob = np.exp(ntwk_base.gain * inputs) prob /= prob.sum() p_replay_no_lingering *= prob[node_next] lingering_inputs = np.zeros((n_nodes,), dtype=float) lingering_inputs[np.array(driven_path)] = LINGERING_INPUT_VALUE p_replay_with_lingering = 1 for node_prev, node_next in zip(driven_path[:-1], driven_path[1:]): intrinsic = ntwk_base.w[:, node_prev] refractory = np.zeros((n_nodes,), dtype=float) refractory[node_prev] = ntwk_base.refractory_strength inputs = intrinsic + refractory + lingering_inputs prob = np.exp(ntwk_base.gain * inputs) prob /= prob.sum() p_replay_with_lingering *= prob[node_next] axs[0].bar([0, 1], [p_replay_no_lingering, p_replay_with_lingering], align='center') axs[0].set_xticks([0, 1]) axs[0].set_xticklabels(['Without \n nonassociative \n priming', 'With \n nonassociative \n priming']) axs[0].set_ylabel('sequence replay probability') for ax, gain in zip(axs[1:], [GAIN_LOW, GAIN_HIGH]): # show expected number of spontaneous replays with and without nonassociative priming ntwk_no_nap = deepcopy(ntwk_base) ntwk_no_nap.gain = gain ntwk_with_nap = deepcopy(ntwk_base) ntwk_with_nap.gain = gain ntwk_with_nap.lingering_input_value = LINGERING_INPUT_VALUE ntwk_with_nap.lingering_input_timescale = LINGERING_INPUT_TIMESCALE drives = np.zeros((T_SPONTANEOUS, n_nodes), dtype=float) for t, node in enumerate(driven_path): drives[t, node] = STRONG_DRIVE_AMPLITUDE past_occurrences_of_driven_seq_no_nap = [] for _ in range(SPONTANEOUS_REPEATS): ntwk = deepcopy(ntwk_no_nap) ntwk.store_voltages = True for drive in drives: ntwk.step(drive) activation_seq = np.array(ntwk.rs_history).nonzero()[1] past_occurrences_of_driven_seq_no_nap.append( metrics.get_number_of_past_occurrences_of_specific_sequence(activation_seq, driven_path) ) past_occurrences_of_driven_seq_no_nap = np.array(past_occurrences_of_driven_seq_no_nap) past_occurrences_of_driven_seq_no_nap_mean = np.mean(past_occurrences_of_driven_seq_no_nap, axis=0) past_occurrences_of_driven_seq_no_nap_sem = stats.sem(past_occurrences_of_driven_seq_no_nap, axis=0) past_occurrences_of_driven_seq_with_nap = [] for _ in range(SPONTANEOUS_REPEATS): ntwk = deepcopy(ntwk_with_nap) ntwk.store_voltages = True for drive in drives: ntwk.step(drive) activation_seq = np.array(ntwk.rs_history).nonzero()[1] past_occurrences_of_driven_seq_with_nap.append( metrics.get_number_of_past_occurrences_of_specific_sequence(activation_seq, driven_path) ) past_occurrences_of_driven_seq_with_nap = np.array(past_occurrences_of_driven_seq_with_nap) past_occurrences_of_driven_seq_with_nap_mean = np.mean(past_occurrences_of_driven_seq_with_nap, axis=0) past_occurrences_of_driven_seq_with_nap_sem = stats.sem(past_occurrences_of_driven_seq_with_nap, axis=0) ts = np.arange(T_SPONTANEOUS) ax.plot(ts, past_occurrences_of_driven_seq_no_nap_mean, color='b', lw=2) ax.fill_between( ts, past_occurrences_of_driven_seq_no_nap_mean - past_occurrences_of_driven_seq_no_nap_sem, past_occurrences_of_driven_seq_no_nap_mean + past_occurrences_of_driven_seq_no_nap_sem, color='b', alpha=0.3, ) ax.plot(ts, past_occurrences_of_driven_seq_with_nap_mean, color='g', lw=2) ax.fill_between( ts, past_occurrences_of_driven_seq_with_nap_mean - past_occurrences_of_driven_seq_with_nap_sem, past_occurrences_of_driven_seq_with_nap_mean + past_occurrences_of_driven_seq_with_nap_sem, color='g', alpha=0.3, ) ax.set_xlabel('time step') ax.set_ylabel('past occurrences') ax.set_title('gain = {}'.format(gain)) ax.legend(['Without nonasso-\n ciative priming', 'With nonasso- \n ciative priming'], loc='best') for ax in axs: axis_tools.set_fontsize(ax, FONT_SIZE)
def basic_replay_ex(CONFIG): """ Run a simulation demonstrating the basic capability of a network with nonassociative priming to demonstrated replay, both triggered and spontaneous. """ SEED = CONFIG['SEED'] LOAD_FILE_NAME = CONFIG['LOAD_FILE_NAME'] GAIN_HIGH = CONFIG['GAIN_HIGH'] GAIN_LOW = CONFIG['GAIN_LOW'] LINGERING_INPUT_VALUE = CONFIG['LINGERING_INPUT_VALUE'] LINGERING_INPUT_TIMESCALE = CONFIG['LINGERING_INPUT_TIMESCALE'] STRONG_DRIVE_AMPLITUDE = CONFIG['STRONG_DRIVE_AMPLITUDE'] WEAK_DRIVE_AMPLITUDE = CONFIG['WEAK_DRIVE_AMPLITUDE'] TRIAL_LENGTH_TRIGGERED_REPLAY = CONFIG['TRIAL_LENGTH_TRIGGERED_REPLAY'] RUN_LENGTH = CONFIG['RUN_LENGTH'] FIG_SIZE = CONFIG['FIG_SIZE'] FONT_SIZE = CONFIG['FONT_SIZE'] np.random.seed(SEED) ntwk_base = np.load(LOAD_FILE_NAME)[0] ntwk_base.lingering_input_value = LINGERING_INPUT_VALUE ntwk_base.lingering_input_timescale = LINGERING_INPUT_TIMESCALE fig = plt.figure(figsize=FIG_SIZE, tight_layout=True) axs = [] axs.append(fig.add_subplot(6, 2, 1)) axs.append(fig.add_subplot(6, 2, 2)) axs.append(fig.add_subplot(6, 2, 3)) axs.append(fig.add_subplot(6, 2, 4)) axs.append(fig.add_subplot(6, 1, 3)) axs.append(fig.add_subplot(6, 1, 4)) axs.append(fig.add_subplot(6, 1, 5)) axs.append(fig.add_subplot(6, 1, 6)) # play sequences aligned to the network's intrinsic path structure path_00 = ntwk_base.node_0_path_tree[0] path_10 = ntwk_base.node_1_path_tree[0] # drive network for first trial: path_00 drives = np.zeros((TRIAL_LENGTH_TRIGGERED_REPLAY, ntwk_base.w.shape[1]), dtype=float) drives[0, path_00[0]] = STRONG_DRIVE_AMPLITUDE for t_ctr, node in enumerate(path_00[1:]): drives[t_ctr + 1, node] = WEAK_DRIVE_AMPLITUDE drives[len(path_00), path_00[0]] = STRONG_DRIVE_AMPLITUDE ntwk = deepcopy(ntwk_base) ntwk.gain = GAIN_HIGH ntwk.store_voltages = True for drive in drives: ntwk.step(drive) spikes = np.array(ntwk.rs_history) fancy_raster.by_row_circles(axs[0], spikes, drives) axs[0].set_xlim(-1, len(drives)) axs[0].set_ylim(-1, 20) axs[0].set_xlabel('time step') axs[0].set_ylabel('active ensemble') axs[0].set_title('Aligning external drive with \n strongly connected paths') # drive network for first trial: path_10 drives = np.zeros((TRIAL_LENGTH_TRIGGERED_REPLAY, ntwk_base.w.shape[1]), dtype=float) drives[0, path_10[0]] = STRONG_DRIVE_AMPLITUDE for t_ctr, node in enumerate(path_10[1:]): drives[t_ctr + 1, node] = WEAK_DRIVE_AMPLITUDE drives[len(path_10), path_10[0]] = STRONG_DRIVE_AMPLITUDE ntwk = deepcopy(ntwk_base) ntwk.gain = GAIN_HIGH ntwk.store_voltages = True for drive in drives: ntwk.step(drive) spikes = np.array(ntwk.rs_history) fancy_raster.by_row_circles(axs[1], spikes, drives) axs[1].set_xlim(-1, len(drives)) axs[1].set_ylim(-1, 20) axs[1].set_xlabel('time step') axs[1].set_ylabel('active ensemble') axs[1].set_title('Aligning external drive with \n strongly connected paths') # drive network for third trial: all path_00 except for element 2 path = list(path_00[:]) path[2] = path_10[2] drives = np.zeros((TRIAL_LENGTH_TRIGGERED_REPLAY, ntwk_base.w.shape[1]), dtype=float) drives[0, path[0]] = STRONG_DRIVE_AMPLITUDE for t_ctr, node in enumerate(path[1:]): drives[t_ctr + 1, node] = WEAK_DRIVE_AMPLITUDE drives[len(path), path[0]] = STRONG_DRIVE_AMPLITUDE ntwk = deepcopy(ntwk_base) ntwk.gain = GAIN_HIGH ntwk.store_voltages = True for drive in drives: ntwk.step(drive) spikes = np.array(ntwk.rs_history) fancy_raster.by_row_circles(axs[2], spikes, drives) axs[2].set_xlim(-1, len(drives)) axs[2].set_ylim(-1, 20) axs[2].set_xlabel('time step') axs[2].set_ylabel('active ensemble') axs[2].set_title('Aligning external drive with \n nonexisting path') # drive network for fourth trial: all path_10 except for element 2 path = list(path_10[:]) path[2] = path_00[2] drives = np.zeros((TRIAL_LENGTH_TRIGGERED_REPLAY, ntwk_base.w.shape[1]), dtype=float) drives[0, path[0]] = STRONG_DRIVE_AMPLITUDE for t_ctr, node in enumerate(path[1:]): drives[t_ctr + 1, node] = WEAK_DRIVE_AMPLITUDE drives[len(path), path[0]] = STRONG_DRIVE_AMPLITUDE ntwk = deepcopy(ntwk_base) ntwk.gain = GAIN_HIGH ntwk.store_voltages = True for drive in drives: ntwk.step(drive) spikes = np.array(ntwk.rs_history) fancy_raster.by_row_circles(axs[3], spikes, drives) axs[3].set_xlim(-1, len(drives)) axs[3].set_ylim(-1, 20) axs[3].set_xlabel('time step') axs[3].set_ylabel('active ensemble') axs[3].set_title('Aligning external drive with \n nonexisting path') # play sequence and then let network run spontaneously for a while drives = np.zeros((RUN_LENGTH, ntwk_base.w.shape[1]), dtype=float) for t_ctr, node in enumerate(path_00): drives[t_ctr, node] = STRONG_DRIVE_AMPLITUDE ntwk = deepcopy(ntwk_base) ntwk.gain = GAIN_HIGH ntwk.store_voltages = True for drive in drives: ntwk.step(drive) spikes = np.array(ntwk.rs_history) fancy_raster.by_row_circles(axs[4], spikes, drives) axs[4].set_xlim(-1, len(drives)) axs[4].set_ylim(-1, ntwk_base.w.shape[1]) axs[4].set_xlabel('time step') axs[4].set_ylabel('active ensemble') axs[4].set_title('Letting network run freely after driving strongly connected path (high gain)') # play sequence and then let network run spontaneously for a while, now with lower gain drives = np.zeros((RUN_LENGTH, ntwk_base.w.shape[1]), dtype=float) for t_ctr, node in enumerate(path_00): drives[t_ctr, node] = STRONG_DRIVE_AMPLITUDE ntwk = deepcopy(ntwk_base) ntwk.gain = GAIN_LOW ntwk.store_voltages = True for drive in drives: ntwk.step(drive) spikes = np.array(ntwk.rs_history) fancy_raster.by_row_circles(axs[5], spikes, drives) axs[5].set_xlim(-1, len(drives)) axs[5].set_ylim(-1, ntwk_base.w.shape[1]) axs[5].set_xlabel('time step') axs[5].set_ylabel('active ensemble') axs[5].set_title('Letting network run freely after driving strongly connected path (low gain)') # let network run spontaneously for a while with no initial drive ntwk = deepcopy(ntwk_base) ntwk.gain = GAIN_HIGH ntwk.store_voltages = True for _ in range(RUN_LENGTH): ntwk.step() spikes = np.array(ntwk.rs_history) fancy_raster.by_row_circles(axs[6], spikes, drives=None) axs[6].set_xlim(-1, len(drives)) axs[6].set_ylim(-1, ntwk_base.w.shape[1]) axs[6].set_xlabel('time step') axs[6].set_ylabel('active ensemble') axs[6].set_title('Letting network run freely with no drive (high gain)') # let network run spontaneously for a while with no initial drive, now with lower gain ntwk = deepcopy(ntwk_base) ntwk.gain = GAIN_LOW ntwk.store_voltages = True for _ in range(RUN_LENGTH): ntwk.step() spikes = np.array(ntwk.rs_history) fancy_raster.by_row_circles(axs[7], spikes, drives=None) axs[7].set_xlim(-1, len(drives)) axs[7].set_ylim(-1, ntwk_base.w.shape[1]) axs[7].set_xlabel('time step') axs[7].set_ylabel('active ensemble') axs[7].set_title('Letting network run freely with no drive (low gain)') for ax in axs: axis_tools.set_fontsize(ax, FONT_SIZE)
def main(config): # get params from config SEED = config['SEED'] DURATION = config['DURATION'] TAU = config['TAU'] V_REST = config['V_REST'] THRESHOLD = config['THRESHOLD'] STEEPNESS = config['STEEPNESS'] NOISE_LEVEL = config['NOISE_LEVEL'] W_FS = config['W_FS'] W_FF = config['W_FF'] W_FI = config['W_FI'] W_XFI = config['W_XFI'] W_IF = config['W_IF'] SWITCH_DRIVE = config['SWITCH_DRIVE'] FONT_SIZE = config['FONT_SIZE'] COLOR_CYCLE = config['COLOR_CYCLE'] ## run simulation with single WTA unit # setup network parameters; order: (switch, fast, fast_inh) w_single = np.array([ [0, 0, 0], # to switch [W_FS, W_FF, W_FI], # to fast [0, W_IF, 0], # to fast_inh ]) nodes_single = 3 * [{'tau': TAU, 'v_rest': V_REST, 'threshold': THRESHOLD, 'steepness': STEEPNESS}] # build network ntwk = network.RateBasedModel(nodes_single, w_single) ntwk.noise_level = NOISE_LEVEL ntwk.store_voltages = True # set network drive drive = np.array([SWITCH_DRIVE, 0, 0]) # run network np.random.seed(SEED) ntwk.vs = np.array([V_REST, V_REST, V_REST]) for t in range(DURATION): ntwk.step(drive) # make figure fig, axs = plt.subplots(2, 1, figsize=(15, 5), sharex=True, tight_layout=True) for ax in axs: ax.set_color_cycle(COLOR_CYCLE) axs[0].plot(ntwk.vs_history, lw=2) axs[1].plot(ntwk.rs_history, lw=2) axs[1].set_ylim(-.1, 1.1) axs[1].set_yticks(np.linspace(0, 1, 5, endpoint=True)) axs[0].set_ylabel('Voltage') axs[1].set_xlabel('t') axs[1].set_ylabel('Firing rate') axs[0].set_title('Single WTA Unit') for ax in axs: axis_tools.set_fontsize(ax, FONT_SIZE) ## run simulation with three non-interacting WTA units # setup network parameters; order: (switch, fast, fast_inh, fast, fast_inh, fast, fast_inh) w_multi = np.array([ [0, 0, 0, 0, 0, 0, 0], # to switch [W_FS, W_FF, W_FI, 0, 0, 0, 0], # to fast1 [0, W_IF, 0, 0, 0, 0, 0], # to fast_inh1 [W_FS, 0, 0, W_FF, W_FI, 0, 0], # to fast2 [0, 0, 0, W_IF, 0, 0, 0], # to fast_inh2 [W_FS, 0, 0, 0, 0, W_FF, W_FI], # to fast3 [0, 0, 0, 0, 0, W_IF, 0], # to fast_inh3 ]) nodes_multi = 7 * [{'tau': TAU, 'v_rest': V_REST, 'threshold': THRESHOLD, 'steepness': STEEPNESS}] # build network ntwk = network.RateBasedModel(nodes_multi, w_multi) ntwk.noise_level = NOISE_LEVEL ntwk.store_voltages = True # set network drive drive = np.array([SWITCH_DRIVE, 0, 0, 0, 0, 0, 0]) # run network np.random.seed(SEED) ntwk.vs = np.array([V_REST, V_REST, V_REST, V_REST, V_REST, V_REST, V_REST]) for t in range(DURATION): ntwk.step(drive) # make figure fig, axs = plt.subplots(2, 1, figsize=(15, 5), sharex=True, tight_layout=True) for ax in axs: ax.set_color_cycle(COLOR_CYCLE) axs[0].plot(np.array(ntwk.vs_history)[:, [1, 3, 5]], lw=2) axs[1].plot(np.array(ntwk.rs_history)[:, [1, 3, 5]], lw=2) axs[1].set_ylim(-.1, 1.1) axs[1].set_yticks(np.linspace(0, 1, 5, endpoint=True)) axs[0].set_ylabel('Voltage') axs[1].set_xlabel('t') axs[1].set_ylabel('Firing rate') axs[0].set_title('Three Independent WTA Units') for ax in axs: axis_tools.set_fontsize(ax, FONT_SIZE) ## run simulation with three interacting WTA units # setup network parameters; order: (switch, fast1, fast_inh1, fast2, fast_inh2, fast3, fast_inh3) w_multi = np.array([ [0, 0, 0, 0, 0, 0, 0], # to switch [W_FS, W_FF, W_FI, 0, W_XFI, 0, W_XFI], # to fast1 [0, W_IF, 0, 0, 0, 0, 0], # to fast_inh1 [W_FS, 0, W_XFI, W_FF, W_FI, 0, W_XFI], # to fast2 [0, 0, 0, W_IF, 0, 0, 0], # to fast_inh2 [W_FS, 0, W_XFI, 0, W_XFI, W_FF, W_FI], # to fast3 [0, 0, 0, 0, 0, W_IF, 0], # to fast_inh3 ]) nodes_multi = 7 * [{'tau': TAU, 'v_rest': V_REST, 'threshold': THRESHOLD, 'steepness': STEEPNESS}] # build network ntwk = network.RateBasedModel(nodes_multi, w_multi) ntwk.noise_level = NOISE_LEVEL ntwk.store_voltages = True # set network drive drive = np.array([SWITCH_DRIVE, 0, 0, 0, 0, 0, 0]) # run network np.random.seed(SEED) ntwk.vs = np.array([V_REST, V_REST, V_REST, V_REST, V_REST, V_REST, V_REST]) for t in range(DURATION): ntwk.step(drive) # make figure fig, axs = plt.subplots(2, 1, figsize=(15, 5), sharex=True, tight_layout=True) for ax in axs: ax.set_color_cycle(COLOR_CYCLE) axs[0].plot(np.array(ntwk.vs_history)[:, [1, 3, 5]], lw=2) axs[1].plot(np.array(ntwk.rs_history)[:, [1, 3, 5]], lw=2) axs[1].set_ylim(-.1, 1.1) axs[1].set_yticks(np.linspace(0, 1, 5, endpoint=True)) axs[0].set_ylabel('Voltage') axs[1].set_xlabel('t') axs[1].set_ylabel('Firing rate') axs[0].set_title('Three Interacting WTA Units') for ax in axs: axis_tools.set_fontsize(ax, FONT_SIZE) ## run simulation with three fast units all of whose interactions occur through one inhibitory unit # setup network parameters; order: (switch, inh, fast1, fast2, fast3) w_multi = np.array([ [0, 0, 0, 0, 0], # to switch [0, 0, W_IF, W_IF, W_IF], # to inh [W_FS, W_FI, W_FF, 0, 0], # to fast1 [W_FS, W_FI, 0, W_FF, 0], # to fast2 [W_FS, W_FI, 0, 0, W_FF], # to fast3 ]) nodes_multi = 5 * [{'tau': TAU, 'v_rest': V_REST, 'threshold': THRESHOLD, 'steepness': STEEPNESS}] # build network ntwk = network.RateBasedModel(nodes_multi, w_multi) ntwk.noise_level = NOISE_LEVEL ntwk.store_voltages = True # set network drive drive = np.array([SWITCH_DRIVE, 0, 0, 0, 0]) # run network np.random.seed(SEED) ntwk.vs = np.array([V_REST, V_REST, V_REST, V_REST, V_REST]) for t in range(DURATION): ntwk.step(drive) # make figure fig, axs = plt.subplots(2, 1, figsize=(15, 5), sharex=True, tight_layout=True) for ax in axs: ax.set_color_cycle(COLOR_CYCLE) axs[0].plot(np.array(ntwk.vs_history)[:, 2:], lw=2) axs[1].plot(np.array(ntwk.rs_history)[:, 2:], lw=2) axs[1].set_ylim(-.1, 1.1) axs[1].set_yticks(np.linspace(0, 1, 5, endpoint=True)) axs[0].set_ylabel('Voltage') axs[1].set_xlabel('t') axs[1].set_ylabel('Firing rate') axs[0].set_title('Three Exc Units Sharing One Inh Unit') for ax in axs: axis_tools.set_fontsize(ax, FONT_SIZE) ## run simulation with many fast units all of whose interactions occur through one inhibitory unit # setup network parameters; order: (switch, inh, fast1, fast2, fast3) w_multi = np.array([ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], # to switch [0, 0, W_IF, W_IF, W_IF, W_IF, W_IF, W_IF, W_IF, W_IF], # to inh [W_FS, W_FI, W_FF, 0, 0, 0, 0, 0, 0, 0], # to fast1 [W_FS, W_FI, 0, W_FF, 0, 0, 0, 0, 0, 0], # to fast2 [W_FS, W_FI, 0, 0, W_FF, 0, 0, 0, 0, 0], # to fast3 [W_FS, W_FI, 0, 0, 0, W_FF, 0, 0, 0, 0], # to fast3 [W_FS, W_FI, 0, 0, 0, 0, W_FF, 0, 0, 0], # to fast3 [W_FS, W_FI, 0, 0, 0, 0, 0, W_FF, 0, 0], # to fast3 [W_FS, W_FI, 0, 0, 0, 0, 0, 0, W_FF, 0], # to fast3 [W_FS, W_FI, 0, 0, 0, 0, 0, 0, 0, W_FF], # to fast3 ]) nodes_multi = 10 * [{'tau': TAU, 'v_rest': V_REST, 'threshold': THRESHOLD, 'steepness': STEEPNESS}] # build network ntwk = network.RateBasedModel(nodes_multi, w_multi) ntwk.noise_level = NOISE_LEVEL ntwk.store_voltages = True # set network drive drive = np.array([SWITCH_DRIVE, 0, 0, 0, 0, 0, 0, 0, 0, 0]) # run network np.random.seed(SEED) ntwk.vs = np.array([V_REST, V_REST, V_REST, V_REST, V_REST, V_REST, V_REST, V_REST, V_REST, V_REST]) for t in range(DURATION): ntwk.step(drive) # make figure fig, axs = plt.subplots(2, 1, figsize=(15, 5), sharex=True, tight_layout=True) for ax in axs: ax.set_color_cycle(COLOR_CYCLE) axs[0].plot(np.array(ntwk.vs_history)[:, 2:], lw=2) axs[1].plot(np.array(ntwk.rs_history)[:, 2:], lw=2) axs[1].set_ylim(-.1, 1.1) axs[1].set_yticks(np.linspace(0, 1, 5, endpoint=True)) axs[0].set_ylabel('Voltage') axs[1].set_xlabel('t') axs[1].set_ylabel('Firing rate') axs[0].set_title('Eight Exc Units Sharing One Inh Unit') for ax in axs: axis_tools.set_fontsize(ax, FONT_SIZE)