def show_sim_stats(data): """ Print a few statistics about a simulation. """ X, X2 = data['X'], data['X2'] n1, n2 = data['n_ex'], data['n_in'] duration = data['duration'] dt, shift = 5, 5 start = 1000 end = duration ma, t = psd.moving_average(X, dt, shift, start, end) ma2, _ = psd.moving_average(X2, dt, shift, start, end) mean1 = 100.0 * ma.mean() / n1 mean2 = 100.0 * ma2.mean() / n2 mean_tot = 100.0 * (ma + ma2).mean() / (n1 + n2) print("Simulation lasted {} seconds".format(duration // 1000)) print("Number of spikes") print("\tExcitatory: {:,} spikes".format(len(X))) print("\tInhibitory: {:,} spikes".format(len(X2))) print("\tTotal: {:,} spikes".format(len(X2) + len(X))) print("Mean firing rate of the network:") print("\tExcitatory population: {:.2f}%".format(mean1)) print("\tInhibitory population: {:.2f}%".format(mean2)) print("\tAll neurons: {:.2f}%".format(mean_tot))
def plot_ma(n, x, dt, shift, ax=None, start=None, end=None, **kwargs): #color=None, label=None): """ Plots the moving average firing rate of a simulation, given the times associated to spikes as ``x``. The output is normalized as a percentage of the number of neurons ``n``. See psd.moving_average for details of the use of ``dt`` and ``shift``. """ if not start: start = 1000 if not end: end = max(start, max(x)) ma, t = psd.moving_average(x, dt, shift, start, end) ma = 100.0 * ma / n if not ax: _, ax = plt.subplots() #ax.set_xlabel('Time (ms)', fontsize=18) ax.set_ylabel('Firing rate\n (% neurons/ms)') ax.plot(t, ma, **kwargs) #color=color, label=label)
def _calc_lz_mod(mod, modules, dt, shift, start, end): """ Calculates the Lempel-Ziv complexity of a single module. """ x, _ = psd.moving_average(modules[mod], dt, shift, start, end) binx = (x > x.mean()).astype(int) return LZ76(binx)
index += 1 X = X[index:] Y = Y[index:] echo_end(echo) echo = echo_start( "Separating list of spikes into separate lists for each module... ") modules = [[] for _ in range(N_MOD)] for spike_t, spike_idx in zip(X, Y): modules[spike_idx // N_EX_MOD].append(spike_t) echo_end(echo) dt = 75 # ms shift = 10 # ms echo = echo_start("Calculating Lempel Ziv Complexity of firing rates... ") lz_comp = np.zeros(N_MOD) for mod in tqdm(range(N_MOD)): x, _ = psd.moving_average(modules[mod], dt, shift, start_time, end_time) binx = (x > x.mean()).astype(int) lz_comp[mod] = LZ76(binx) echo_end(echo) n_steps = float(end_time - start_time) / shift plt.hist(lz_comp * np.log(n_steps) / n_steps) plt.xlabel('Normalized LZ complexity') plt.ylabel('Module counts') plt.show()
X1 = M_EX.t / ms X2 = M_IN.t / ms X = np.concatenate([X1, X2]) Y = np.concatenate([M_EX.i, M_IN.i + N_EX]) XY = [(t, s) for (t, s) in zip(X, Y) if t >= transient_thres] XY = sorted(XY, key=lambda tup: tup[0]) X, Y = zip(*XY) dt = 75 # ms shift = 10 # ms total_steps = int(duration / (shift * ms)) print('Plotting..') plt.figure(1) ma = psd.moving_average(X, dt, shift, total_steps) time_scale = np.arange(0, duration / ms, shift) time_scale = time_scale[100:-100] plt.plot(time_scale, ma[100:-100]) plt.title('All Neurons') plt.xlabel('Simulation Time (ms)') plt.ylabel('Mean firing rate') ma1 = psd.moving_average(X1, dt, shift, total_steps) ma2 = psd.moving_average(X2, dt, shift, total_steps) plt.figure(2) plt.plot(time_scale, ma1[100:-100]) plt.title('Excitatory Neurons') plt.xlabel('Simulation Time (ms)') plt.ylabel('Mean firing rate')
for spike_t, spike_idx in zip(X, Y): if MEASURE_START <= spike_t < MEASURE_START + MEASURE_DURATION and \ spike_idx < 3*40: X1.append(spike_t) Y1.append(spike_idx) print('\tCollect relevant spikes: {}s'.format(time.time() - tt)) #X, Y = M.t/ms, M.i X, Y = X1, Y1 tt = time.time() dt = 10 # ms shift = 5 # ms total_steps = int(duration / (shift * ms)) ma, time_scale = psd.moving_average(X, dt, shift, total_steps, True) print('\tCalculate moving average: {}s'.format(time.time() - tt)) tt = time.time() X2, Y2 = [], [] for ma_val, t in zip(ma, time_scale): if MEASURE_START <= t[0] < MEASURE_START + MEASURE_DURATION: Y2.append(ma_val) X2.append(t[0]) print('\tCollect relvant moving average data points: {}s'.format(time.time() - tt)) plt.subplot(211) plt.plot(X1, Y1, '.b') plt.ylabel('Neuron Index') plt.xlabel('Simulation Time (ms)')
with open(fname, 'rb') as f: DATA = pickle.load(f) [duration, X1, X2] = DATA # Discard initial transient signal transient_thres = 1000 # ms X = np.concatenate([X1, X2]) dt = 75 # ms shift = 10 # ms total_steps = int(duration/shift) print('Plotting..') plt.figure(1) ma = psd.moving_average(X, dt, shift, total_steps) plt.plot(np.arange(0, duration, shift), ma) plt.xlabel('Mean firing rate') plt.ylabel('Simulation Time (ms)') plt.figure(2) f, pxx = psd.power_spectrum(X, dt, shift, total_steps) plt.semilogy(f, pxx) plt.xlabel('Frequency (Hz)') plt.ylabel('Power Spectrum') plt.figure(3) plt.plot(X, Y, '.b') plt.xlabel("Time (ms)") plt.ylabel("Excitatory Neuron Index")
def pci(data, dt, shift, method1=False): """ Calculate Perturbational Complexity Index. Arguments: - data [dict]: must contain the data of a simulation, as obtained by calling ex.run_simulation(with_tms=True) for some experiment. - dt [int/float]: averaging window size for moving average calculations - shift [int/float]: dictates the time intervals between measurements in the moving average calculations. - method1 [bool]: If true, use Method 1, where each modules activity is compared against the mean network pre-stimulus rate to determine if a significant source of activation is present. Otherwise, each module's activity is compared against its own pre-stimulus firing rate. Return: - Normalized PCI index. """ X, Y, n_mod, n_ex_mod, tms_time = [ data[k] for k in ['X', 'Y', 'n_mod', 'n_ex_mod', 'tms_time'] ] t1, t2, t3 = tms_time - t_pre, tms_time, tms_time + t_post # Group spike by modules X = pd.Series(X) Y = pd.Series(Y // n_ex_mod) gb = X.groupby(Y) steps1 = int((t2 - t1) / shift) steps2 = int((t3 - t2) / shift) pre_data = np.zeros(n_mod * steps1) post_data = np.zeros(n_mod * steps2) for mod in gb.groups: # Get spikes associated to module ``mod`` x = np.array(gb.get_group(mod)) msk1 = x < t2 msk2 = np.logical_and(x >= t2, x < t3) # Pre and post TMS moving average for the given module pre_ma = psd.moving_average(x[msk1], dt, shift, t1, t2)[0] post_ma = psd.moving_average(x[msk2], dt, shift, t2, t3)[0] if method1: pre_data[mod * steps1 : (mod + 1) * steps1] = pre_ma post_data[mod * steps2 : (mod + 1) * steps2] = post_ma else: params = pre_ma.mean() + 2 * pre_ma.std() post_data[mod * steps2 : (mod + 1) * steps2] = (post_ma > params).astype(int) # PCI if method1: pre_mean, pre_std = pre_data.mean(), pre_data.std() post_binarized = (post_data > pre_mean + 2 * pre_std).astype(int) lz_complexity = LZ76(post_binarized) * np.log(len(post_data)) / len(post_data) else: post_binarized = post_data lz_complexity = LZ76(post_binarized) * np.log(len(post_data)) / len(post_data) return lz_complexity
spikes = M_EX.i times = M_EX.t / ms # Separate spikes into their modules spikes_per_module = [[] for _ in range(N_MOD)] for idx, t in enumerate(times): mod = spikes[idx] // (N_EX / N_MOD) spikes_per_module[mod].append(t) dt = 75 # ms shift = 10 # ms ts = np.arange(0, duration / ms, shift) ax1 = plt.subplot(313) for i, ss in enumerate(spikes_per_module): ma = psd.moving_average(ss, dt, shift, int((duration / ms) / shift)) plt.plot(ts, ma, color="C{}".format(i), label="Module {}".format(i)) ax1.set_xlim(0, duration / ms) ax1.set_ylabel("Mean firing rate") ax1.set_xlabel("Time (ms)") ax2 = plt.subplot(311) plt.plot(M_EX.t / ms, M_EX.i, '.b') ax2.set_xlim(0, duration / ms) ax2.set_xlabel("Time (ms)") ax2.set_ylabel("Excitatory Neuron Index") ax3 = plt.subplot(312) plt.plot(M_IN.t / ms, M_IN.i, '.k') ax3.set_xlim(0, duration / ms) ax3.set_xlabel("Time (ms)")
def run_experiment(n_mod, duration, connectivity, scaling_factor, log_scaling=False, save_output=False, verbose=False): seed(1357) CIJ = spio.loadmat('data/Conectoma.mat')['CIJ_fbden_average'] XYZ = spio.loadmat('data/coords_sporns_2mm.mat')['coords_new'] # N_MOD = len(XYZ) # Number of modules N_MOD = min(n_mod, len(XYZ)) # Number of modules EX_EX_WEIGHT = 5 * mV EX_IN_WEIGHT = 10 * mV IN_EX_WEIGHT = -10 * mV IN_IN_WEIGHT = -10 * mV DELAY = 5 * ms EX_CONNECTIVITY = 0.4 IN_CONNECTIVITY = 0.1 # Setup N_EX_MOD, N_IN_MOD = 40, 10 N_EX = N_EX_MOD * N_MOD N_IN = N_IN_MOD * N_MOD EX_G = ExcitatoryNeuronGroup(N_EX) EX_G.I = 15 * random_sample(N_EX) * mV / ms IN_G = InhibitoryNeuronGroup(N_IN) IN_G.I = 3 * random_sample(N_IN) * mV / ms # Define all synapse objects EX_EX_SYN = Synapses(EX_G, model='w: volt', on_pre='v += w', delay=DELAY) EX_IN_SYN = Synapses(EX_G, IN_G, model='w: volt', on_pre='v += w', delay=DELAY) IN_EX_SYN = Synapses(IN_G, EX_G, model='w: volt', on_pre='v += w', delay=DELAY) IN_IN_SYN = Synapses(IN_G, IN_G, model='w: volt', on_pre='v += w', delay=DELAY) INTER_EX_EX_SYN = Synapses( EX_G, EX_G, model='w: volt', on_pre='v += w', ) if verbose: echo = echo_start("Setting up synapses... \n") tt = time.time() EX_EX_SYN.connect(condition='int(i/40) == int(j/40)', p=EX_CONNECTIVITY) EX_EX_SYN.w = EX_EX_WEIGHT if verbose: print('\tEX_EX_SYN ({:,} synapses): {}s'.format( len(EX_EX_SYN.w), time.time() - tt)) tt = time.time() EX_IN_SYN.connect(condition='j == int(i/4)') EX_IN_SYN.w = EX_IN_WEIGHT if verbose: print('\tEX_IN_SYN ({:,} synapses): {}s'.format( len(EX_IN_SYN.w), time.time() - tt)) tt = time.time() IN_EX_SYN.connect(condition='int(i/10) == int(j/40)') IN_EX_SYN.w = IN_EX_WEIGHT if verbose: print('\tIN_EX_SYN ({:,} synapses): {}s'.format( len(IN_EX_SYN.w), time.time() - tt)) tt = time.time() IN_IN_SYN.connect(condition='int(i/10) == int(j/10)', p=IN_CONNECTIVITY) IN_IN_SYN.w = IN_IN_WEIGHT if verbose: print('\tIN_IN_SYN ({:,} synapses): {}s'.format( len(IN_IN_SYN.w), time.time() - tt)) # Synapses between modules (only excitatory-excitatory connections will be # created) tt = time.time() synapses = [] delay_matrix = np.zeros((N_MOD, N_MOD)) for i in range(N_MOD): x, y, z = XYZ[i] for j in range(N_MOD): if CIJ[i][j] > 0: # Delay = distance / speed, speed = 2 m/s x2, y2, z2 = XYZ[j] delay_matrix[i][j] = math.sqrt((x - x2)**2 + (y - y2)**2 + (z - z2)**2) / 2 base_i, base_j = i * N_EX_MOD, j * N_EX_MOD synapses += [(base_i + ii, base_j + jj) for ii in range(N_EX_MOD) for jj in range(N_EX_MOD) if sample() < connectivity] synapses_i, synapses_j = map(np.array, zip(*synapses)) INTER_EX_EX_SYN.connect(i=synapses_i, j=synapses_j) INTER_EX_EX_SYN.delay = \ delay_matrix[np.array(synapses_i/N_EX_MOD), np.array(synapses_j/N_EX_MOD)] * ms if log_scaling: INTER_EX_EX_SYN.w = np.log(CIJ[synapses_i/N_EX_MOD, synapses_j/N_EX_MOD]) * \ scaling_factor * mV else: INTER_EX_EX_SYN.w = CIJ[synapses_i/N_EX_MOD, synapses_j/N_EX_MOD] * \ scaling_factor * mV if verbose: print('\tINTER_EX_EX_SYN ({:,} synapses): {}s'.format( len(INTER_EX_EX_SYN.w), time.time() - tt)) echo_end(echo) echo = echo_start("Running sym... ") recorded_neurons = [0, 1, 50, 90] M_EX = SpikeMonitor(EX_G) M_IN = SpikeMonitor(IN_G) M_V = StateMonitor(EX_G, 'v', record=recorded_neurons) run(duration * ms) if verbose: echo_end(echo) echo = echo_start("Processing spike data...") # Problem: inhibitory indexes overlap with excitatory indexes #X = np.concatenate(M_EX.t/ms, M_IN.t/ms) #Y = np.concatenate(M_EX.i, M_IN.i) #perm_sort = X.argsort() #X, Y = X[perm_sort], Y[perm_sort] X, Y = M_EX.t / ms, M_EX.i start_time = 1000 end_time = duration if verbose: echo_end(echo) echo = echo_start( "Selecting spikes between {}ms and {}ms of simulation... ".format( start_time, end_time)) # Discard transient mask = np.logical_and(X >= 1000, X < end_time) X, Y = X[mask], Y[mask] if verbose: echo_end(echo) echo = echo_start( "Separating list of spikes into separate lists for each module... " ) #modules = [[] for _ in range(N_MOD)] #for spike_t, spike_idx in zip(X, Y): # modules[spike_idx // N_EX_MOD].append(spike_t) X_series, Y_series = pd.Series(X), pd.Series(Y // N_EX_MOD) gb = X_series.groupby(Y_series) modules = [[] for _ in range(N_MOD)] for mod in gb.groups: modules[mod] = np.array(gb.get_group(mod)) if verbose: echo_end(echo) echo = echo_start( "Calculating Lempel Ziv Complexity of firing rates... ") dt = 75 # ms shift = 10 # ms lz_comp = np.zeros(N_MOD) for mod in range(N_MOD): x, _ = psd.moving_average(modules[mod], dt, shift, start_time, end_time) binx = (x > x.mean()).astype(int) lz_comp[mod] = LZ76(binx) if verbose: echo_end(echo) n_steps = float(end_time - start_time) / shift params = (n_mod, duration // 1000, connectivity, scaling_factor, int(log_scaling)) plt.figure() plt.hist(lz_comp * np.log(n_steps) / n_steps) plt.xlabel('Normalized LZ complexity') plt.ylabel('Module counts') plt.savefig( 'figures/sim10/sim_10_sweep_lz_complexity_N{}_{}s_{}_{}_{}.png'.format( *params)) plt.figure() mask = np.logical_and.reduce((X >= 3000, X < 3500, Y < 150)) plt.plot(X[mask], Y[mask], '.') plt.xlabel('Simulation Time (ms)') plt.savefig( 'figures/sim10/sim_10_sweep_raster_N{}_{}s_{}_{}_{}.png'.format( *params)) plt.figure() t = M_V.t / ms mask = np.logical_and(t >= 1000, t < 1100) t = t[mask] for idx, neuron_idx in enumerate(recorded_neurons): v = M_V.v[idx] v = v[mask] plt.subplot(2, 2, idx + 1) plt.plot(t, v) plt.ylabel('Neuron {} voltage'.format(neuron_idx)) plt.xlabel('Simulation time (ms)') plt.tight_layout() plt.savefig( 'figures/sim10/sim_10_sweep_neuron_voltage_N{}_{}s_{}_{}_{}.png'. format(*params)) DATA = { 'X': X, 'Y': Y, 'duration': duration, 'N_MOD': N_MOD, 'M_V': M_V, 'M_EX': M_EX, 'M_IN': M_IN, 'lz_comp': lz_comp, 'n_steps': n_steps, } if save_output: fname = "experiment_data/exp10_{}sec.pickle".format( int(duration / 1000)) if verbose: echo = echo_start("Storing data to {}... ".format(fname)) with open(fname, 'wb') as f: pickle.dump(DATA, f) if verbose: echo_end(echo) return DATA