def run_mean_field_extended(NRN1, NRN2, NTWK, array_func,\ Ne=8000, Ni=2000, T=5e-3,\ afferent_exc_fraction=0., dt=1e-4, tstop=2, extended_output=False,\ ext_drive_change=0.): # find external drive M = get_connectivity_and_synapses_matrix(NTWK, SI_units=True) ext_drive = M[0,0]['ext_drive'] if afferent_exc_fraction<0.5: afferent_exc_fraction = M[0,0]['afferent_exc_fraction'] X0 = find_fixed_point(NRN1, NRN2, NTWK, exc_aff=ext_drive+ext_drive_change,\ Ne=Ne, Ni=Ni, verbose=True) TF1, TF2 = load_transfer_functions(NRN1, NRN2, NTWK) t = np.arange(int(tstop/dt))*dt def dX_dt_scalar(X, t=0): exc_aff = ext_drive+ext_drive_change+(1-afferent_exc_fraction)*array_func(t) pure_exc_aff = (2*afferent_exc_fraction-1)*array_func(t) # what needs to be added return build_up_differential_operator(TF1, TF2, Ne=Ne, Ni=Ni, T=T)(X,\ exc_aff=exc_aff, pure_exc_aff=pure_exc_aff) X = np.zeros((len(t), len(X0))) X[0,:] = X0 for i in range(len(t)-1): exc_aff = ext_drive+ext_drive_change+(1-afferent_exc_fraction)*array_func(t[i]) pure_exc_aff = (2*afferent_exc_fraction-1)*array_func(t[i]) # what needs to be added # X[i+1,:] = X[i,:] + dt*dX_dt_scalar(X[i,:], t=t[i]) X[i+1,:] = X[i,:] + (t[1]-t[0])*build_up_differential_operator(TF1, TF2,\ Ne=Ne, Ni=Ni)(X[i,:], exc_aff=exc_aff, pure_exc_aff=pure_exc_aff) fe, fi = X[:,0], X[:,1] sfe, sfei, sfi = [np.sqrt(X[:,i]) for i in range(2,5)] if extended_output: params = get_neuron_params(NRN2, SI_units=True) reformat_syn_parameters(params, M) exc_aff = ext_drive+ext_drive_change+(1-afferent_exc_fraction)*array_func(t) pure_exc_aff = (2*afferent_exc_fraction-1)*array_func(t) # what needs to be added # excitatory neurons have more excitation muV_e, sV_e, muGn_e, TvN_e = get_fluct_regime_vars(\ fe+exc_aff+pure_exc_aff,\ fi, *pseq_params(params)) muV_i, sV_i, muGn_i, TvN_i = get_fluct_regime_vars(\ fe+exc_aff,\ fi, *pseq_params(params)) muV, sV, muGn, TvN = .8*muV_e+.2*muV_i, .8*sV_e+.2*sV_i,\ .8*muGn_e+.2*muGn_i, .8*TvN_e+.2*TvN_i, return t, fe, fi, sfe, sfei, sfi, muV, sV, muGn, TvN else: return t, fe, fi, sfe, sfei, sfi
def run_mean_field(NRN1, NRN2, NTWK, array_func,\ T=5e-3, dt=1e-4, tstop=2, extended_output=False,\ afferent_exc_fraction=0., ext_drive_change=0.): # find external drive M = get_connectivity_and_synapses_matrix(NTWK, SI_units=True) ext_drive = M[0,0]['ext_drive'] if afferent_exc_fraction<0.5: afferent_exc_fraction = M[0,0]['afferent_exc_fraction'] X0 = find_fixed_point_first_order(NRN1, NRN2, NTWK, exc_aff=ext_drive+ext_drive_change,\ verbose=False) TF1, TF2 = load_transfer_functions(NRN1, NRN2, NTWK) t = np.arange(int(tstop/dt))*dt def dX_dt_scalar(X, t=0): exc_aff = ext_drive+ext_drive_change+(1-afferent_exc_fraction)*array_func(t) pure_exc_aff = (2*afferent_exc_fraction-1)*array_func(t) # what needs to be added return build_up_differential_operator_first_order(TF1, TF2, T=T)(X,\ exc_aff=exc_aff, pure_exc_aff=pure_exc_aff) fe, fi = odeint(dX_dt_scalar, X0, t).T if extended_output: params = get_neuron_params(NRN2, SI_units=True) reformat_syn_parameters(params, M) exc_aff = ext_drive+ext_drive_change+(1-afferent_exc_fraction)*array_func(t) pure_exc_aff = (2*afferent_exc_fraction-1)*array_func(t) # what needs to be added # excitatory neurons have more excitation muV_e, sV_e, muGn_e, TvN_e = get_fluct_regime_vars(\ fe+exc_aff+pure_exc_aff,\ fi, *pseq_params(params)) muV_i, sV_i, muGn_i, TvN_i = get_fluct_regime_vars(\ fe+exc_aff,\ fi, *pseq_params(params)) muV, sV, muGn, TvN = .8*muV_e+.2*muV_i, .8*sV_e+.2*sV_i,\ .8*muGn_e+.2*muGn_i, .8*TvN_e+.2*TvN_i, return t, fe, fi, muV, sV, muGn, TvN else: return t, fe, fi
def load_transfer_functions(NRN1, NRN2, NTWK): """ returns the two transfer functions of the mean field model """ print("'../transfer_functions/data/'+NRN1+'_'+NTWK+'_fit.npy'") # NTWK M = get_connectivity_and_synapses_matrix(NTWK, SI_units=True) # NRN1 params1 = get_neuron_params(NRN1, SI_units=True) reformat_syn_parameters(params1, M) try: P1 = np.load('../transfer_functions/data/' + NRN1 + '_' + NTWK + '_fit.npy') #P1=np.load('../transfer_functions/data/'+NRN1+'_'+NTWK+'_DB_fit.npy') params1['P'] = P1 def TF1(fe, fi): return TF_my_template(fe, fi, *pseq_params(params1)) except IOError: print('=======================================================') print('===== fit for NRN1 not available ====================') print('=======================================================') # NRN1 params2 = get_neuron_params(NRN2, SI_units=True) reformat_syn_parameters(params2, M) try: P2 = np.load('../transfer_functions/data/' + NRN2 + '_' + NTWK + '_fit.npy') params2['P'] = P2 def TF2(fe, fi): return TF_my_template(fe, fi, *pseq_params(params2)) except IOError: print('=======================================================') print('===== fit for NRN2 not available ====================') print('=======================================================') return TF1, TF2
def plot_ntwk_sim_output_for_waveform(args,\ BIN=5, min_time=200, bar_ms=50, zoom_conditions=None, vpeak=-35,\ raster_number=400): BIN = 8 time_array, rate_array, rate_exc, rate_inh,\ Raster_exc, Raster_inh,\ Vm_exc, Vm_inh, Ge_exc, Ge_inh, Gi_exc, Gi_inh = np.load(args.file,allow_pickle = True) rate_exc = rate_exc + 0.2 print("ee") if zoom_conditions is not None: z = zoom_conditions else: z = [time_array[0], time_array[-1]] cond_t = (time_array > z[0]) & (time_array < z[1]) ###### =========================================== ###### ############# adding the theoretical eval ############### ###### =========================================== ###### t0 = args.t0 - 4 * args.T1 def rate_func(t): return double_gaussian(t, 1e-3 * args.t0, 1e-3 * args.T1, 1e-3 * args.T2, args.amp) t, fe, fi, sfe, sfei, sfi = run_mean_field_extended(args.CONFIG.split('--')[0],\ args.CONFIG.split('--')[1],args.CONFIG.split('--')[2],\ rate_func,dt=5e-4, tstop=args.tstop*1e-3) tfirst, fefirst, fifirst = run_mean_field(args.CONFIG.split('--')[0], args.CONFIG.split('--')[1], args.CONFIG.split('--')[2], rate_func, dt=5e-4, tstop=args.tstop * 1e-3) params = get_neuron_params(args.CONFIG.split('--')[0], SI_units=True) M = get_connectivity_and_synapses_matrix('CONFIG1', SI_units=True) reformat_syn_parameters(params, M) # merging those parameters ext_drive = M[0, 0]['ext_drive'] afferent_exc_fraction = M[0, 0]['afferent_exc_fraction'] fe_e, fe_i = fe + ext_drive + rate_func(t), fe + ext_drive muV_e, sV_e, muGn_e, TvN_e = get_fluct_regime_vars(fe_e, fi, *pseq_params(params)) muV_i, sV_i, muGn_i, TvN_i = get_fluct_regime_vars(fe_i, fi, *pseq_params(params)) Ne = Raster_inh[1].min() FIGS = [] # plotting FIGS.append(plt.figure(figsize=(5, 4))) cond = (Raster_exc[0] > z[0]) & (Raster_exc[0] < z[1]) & ( Raster_exc[1] > Ne - raster_number) plt.plot(Raster_exc[0][cond], Raster_exc[1][cond], '.g') cond = (Raster_inh[0] > z[0]) & (Raster_inh[0] < z[1]) & ( Raster_inh[1] < Ne + .2 * raster_number) plt.plot(Raster_inh[0][cond], Raster_inh[1][cond], '.r') ''' plt.plot([z[0],z[0]+bar_ms], [Ne, Ne], 'k-', lw=5) plt.annotate(str(bar_ms)+'ms', (z[0]+bar_ms, Ne)) ''' #set_plot(plt.gca(), ['left'], ylabel='Neuron index', xticks=[]) FIGS.append(plt.figure(figsize=(5, 5))) ax1 = plt.subplot2grid((3, 1), (0, 0), rowspan=2) ax2 = plt.subplot2grid((3, 1), (2, 0)) for i in range(len(Vm_exc)): ax1.plot(time_array[cond_t], Vm_exc[i][cond_t], 'g-', lw=.5) spk = np.where((Vm_exc[i][cond_t][:-1] > -50) & (Vm_exc[i][cond_t][1:] < -55))[0] for ispk in spk: ax1.plot(time_array[cond_t][ispk] * np.ones(2), [Vm_exc[i][cond_t][ispk], vpeak], 'g--') ax2.plot(time_array[cond_t], Ge_exc[i][cond_t], 'g-', lw=.5) ax2.plot(time_array[cond_t], Gi_exc[i][cond_t], 'r-', lw=.5) # vm ax1.plot(1e3 * t[1e3 * t > t0], 1e3 * muV_e[1e3 * t > t0], 'g-', lw=2) ax1.fill_between(1e3*t[1e3*t>t0], 1e3*(muV_e[1e3*t>t0]-sV_e[1e3*t>t0]),\ 1e3*(muV_e[1e3*t>t0]+sV_e[1e3*t>t0]), color='g', alpha=.4) # ge ge_th = 1e9 * fe_e[1e3 * t > t0] * params['Qe'] * params['Te'] * ( 1 - params['gei']) * params['pconnec'] * params['Ntot'] sge_th = 1e9 * params['Qe'] * np.sqrt( fe_e[1e3 * t > t0] * params['Te'] * (1 - params['gei']) * params['pconnec'] * params['Ntot']) ax2.plot(1e3 * t[1e3 * t > t0], ge_th, 'g-', lw=2) ax2.fill_between(1e3 * t[1e3 * t > t0], ge_th - sge_th, ge_th + sge_th, color='g', alpha=.4) gi_th = 1e9 * fi[1e3 * t > t0] * params['Qi'] * params['Ti'] * params[ 'gei'] * params['pconnec'] * params['Ntot'] sgi_th = 1e9 * params['Qi'] * np.sqrt( fi[1e3 * t > t0] * params['Ti'] * params['gei'] * params['pconnec'] * params['Ntot']) ax2.plot(1e3 * t[1e3 * t > t0], gi_th, 'r-', lw=2) ax2.fill_between(1e3 * t[1e3 * t > t0], gi_th - sgi_th, gi_th + sgi_th, color='r', alpha=.4) ax1.plot(time_array[cond_t][0] * np.ones(2), [-65, -55], lw=4, color='k') ax1.annotate('10mV', (time_array[cond_t][0], -65)) #set_plot(ax1, [], xticks=[], yticks=[]) #set_plot(ax2, ['left'], ylabel='$G$ (nS)', xticks=[]) FIGS.append(plt.figure(figsize=(5, 5))) ax1 = plt.subplot2grid((3, 1), (0, 0), rowspan=2) ax2 = plt.subplot2grid((3, 1), (2, 0)) for i in range(len(Vm_inh)): ax1.plot(time_array[cond_t], Vm_inh[i][cond_t], 'r-', lw=.5) spk = np.where((Vm_inh[i][cond_t][:-1] > -51) & (Vm_inh[i][cond_t][1:] < -55))[0] for ispk in spk: ax1.plot(time_array[cond_t][ispk] * np.ones(2), [Vm_inh[i][cond_t][ispk], vpeak], 'r--') ax2.plot(time_array[cond_t], Ge_inh[i][cond_t], 'g-', lw=.5) ax2.plot(time_array[cond_t], Gi_inh[i][cond_t], 'r-', lw=.5) # vm ax1.plot(1e3 * t[1e3 * t > t0], 1e3 * muV_i[1e3 * t > t0], 'r-', lw=2) ax1.fill_between(1e3*t[1e3*t>t0], 1e3*(muV_i[1e3*t>t0]-sV_i[1e3*t>t0]),\ 1e3*(muV_i[1e3*t>t0]+sV_i[1e3*t>t0]), color='r', alpha=.4) ge_th = 1e9 * fe_i[1e3 * t > t0] * params['Qe'] * params['Te'] * ( 1 - params['gei']) * params['pconnec'] * params['Ntot'] sge_th = 1e9 * params['Qe'] * np.sqrt( fe_i[1e3 * t > t0] * params['Te'] * (1 - params['gei']) * params['pconnec'] * params['Ntot']) ax2.plot(1e3 * t[1e3 * t > t0], ge_th, 'g-', lw=2) ax2.fill_between(1e3 * t[1e3 * t > t0], ge_th - sge_th, ge_th + sge_th, color='g', alpha=.4) ax2.plot(1e3 * t[1e3 * t > t0], gi_th, 'r-', lw=2) ax2.fill_between(1e3 * t[1e3 * t > t0], gi_th - sgi_th, gi_th + sgi_th, color='r', alpha=.4) ax1.plot(time_array[cond_t][0] * np.ones(2), [-65, -55], lw=4, color='k') ax1.annotate('10mV', (time_array[cond_t][0], -65)) #set_plot(ax1, [], xticks=[], yticks=[]) #set_plot(ax2, ['left'], ylabel='$G$ (nS)', xticks=[]) fig, AX = plt.subplots(figsize=(5, 3)) # we bin the population rate rate_exc = bin_array(rate_exc[cond_t], BIN, time_array[cond_t]) rate_inh = bin_array(rate_inh[cond_t], BIN, time_array[cond_t]) rate_array = bin_array(rate_array[cond_t], BIN, time_array[cond_t]) time_array = bin_array(time_array[cond_t], BIN, time_array[cond_t]) AX.plot(time_array, rate_exc, 'g-', lw=.6, label='$\\nu_e(t)$') AX.plot(time_array, rate_inh, 'r-', lw=.6, label='$\\nu_i(t)$') AX.plot(1000 * tfirst, fifirst, 'r--', lw=.6, label='$\\nu_i(t)$') np.save('HH_response', [ 1000 * tfirst, fefirst, fifirst, t, fe, fi, sfe, sfi, rate_func(tfirst) ]) #AX.plot(time_array, .8*rate_exc+.2*rate_inh, 'k-', lw=2, label='$\\nu(t)$') AX.plot(1e3 * t[1e3 * t > t0], fi[1e3 * t > t0], 'r-', label='num. sim.') AX.plot(1e3*t[1e3*t>t0], rate_func(t[1e3*t>t0]), 'k:',\ lw=2, label='$\\nu_e^{aff}(t)$ \n $\\nu_e^{drive}$') AX.plot(1e3 * t[1e3 * t > t0], fe[1e3 * t > t0], 'g-', label='mean field \n pred.') AX.fill_between(1e3*t[1e3*t>t0], fe[1e3*t>t0]-sfe[1e3*t>t0], fe[1e3*t>t0]+sfe[1e3*t>t0],\ color='g', alpha=.3, label='mean field \n pred.') AX.fill_between(1e3*t[1e3*t>t0], fi[1e3*t>t0]-sfi[1e3*t>t0], fi[1e3*t>t0]+sfi[1e3*t>t0],\ color='r', alpha=.3) # AX.plot(1e3*t[1e3*t>t0], .8*fe[1e3*t>t0]+.2*fi[1e3*t>t0], 'k-', label='..') AX.legend(prop={'size': 'xx-small'}) #set_plot(AX, ['left'], ylabel='$\\nu$ (Hz)', xticks=[], num_yticks=3) FIGS.append(fig) print('excitatory rate: ', rate_exc[len(rate_exc) / 2:].mean(), 'Hz') print('inhibitory rate: ', rate_inh[len(rate_exc) / 2:].mean(), 'Hz') print(sfe[0], sfe[-1]) plt.show() return FIGS
def plot_ntwk_sim_output(time_array, rate_array, rate_exc, rate_inh,\ Raster_exc, Raster_inh,\ Vm_exc, Vm_inh, Ge_exc, Ge_inh, Gi_exc, Gi_inh,\ BIN=5, min_time=2000): BIN = 15. cond_t = (time_array > min_time) # transient behavior after 400 ms params = get_neuron_params(args.CONFIG.split('--')[0], SI_units=True) M = get_connectivity_and_synapses_matrix('CONFIG1', SI_units=True) EXC_AFF = M[0, 0]['ext_drive'] print('starting fixed point') fe0, fi0, sfe, sfie, sfi = find_fixed_point(args.CONFIG.split('--')[0], args.CONFIG.split('--')[1], 'CONFIG1',\ exc_aff=EXC_AFF, Ne=8000, Ni=2000, verbose=True) print('end fixed point') reformat_syn_parameters(params, M) # merging those parameters xfe = fe0 + np.linspace(-4, 4) * sfe fe_pred = gaussian_func(xfe, fe0, sfe) xfi = fi0 + np.linspace(-4, 4) * sfi fi_pred = gaussian_func(xfi, fi0, sfi) mGe, mGi, sGe, sGi = mean_and_var_conductance(fe0 + EXC_AFF, fi0, *pseq_params(params)) muV, sV, muGn, TvN = get_fluct_regime_vars(fe0 + EXC_AFF, fi0, *pseq_params(params)) print("eee", muV) FE, FI = np.meshgrid(xfe, xfi) pFE, pFI = np.meshgrid(fe_pred, fi_pred) MUV, SV, _, _ = get_fluct_regime_vars( FE + EXC_AFF, FI, *pseq_params(params)) * pFE * pFI / np.sum(pFE * pFI) ### MEMBRANE POTENTIAL MEAN_VM, STD_VM, KYRT_VM = [], [], [] for i in range(len(Vm_exc)): MEAN_VM.append(Vm_exc[i][(time_array > min_time) & (Vm_exc[i] != -65) & (Vm_exc[i] < -50)].mean()) MEAN_VM.append(Vm_inh[i][(time_array > min_time) & (Vm_inh[i] != -65) & (Vm_inh[i] < -50)].mean()) for vv in [ Vm_exc[i][(time_array > min_time)], Vm_inh[i][(time_array > min_time)] ]: i0 = np.where((vv[:-1] > -52) & (vv[1:] < -60))[0] print(i0) sv = [] if len(i0) == 0: STD_VM.append(vv.std()) elif len(i0) == 1: STD_VM.append(vv[0].std()) else: for i1, i2 in zip(i0[:-1], i0[1:]): if i2 - i1 > 60: sv.append(vv[i1 + 30:i2 - 30].std()) STD_VM.append(np.array(sv).mean()) STD_VM.append(Vm_inh[i][(time_array > min_time) & (Vm_inh[i] < -50)].std()) fig1, AX1 = plt.subplots(1, 3, figsize=(3, 2)) # for means fig2, AX2 = plt.subplots(1, 3, figsize=(3, 2)) # for std AX1[0].bar([0], np.array(MEAN_VM).mean() + 65, yerr=np.array(MEAN_VM).std(), color='w', edgecolor='k', lw=3, error_kw=dict(elinewidth=3, ecolor='k')) AX2[0].bar([0], np.array(STD_VM).mean(), yerr=np.array(STD_VM).std(), color='w', edgecolor='k', lw=3, error_kw=dict(elinewidth=3, ecolor='k'), label='$V_m$') AX1[0].bar([1], [1e3 * muV + 65], color='gray', alpha=.5, label='$V_m$') AX2[0].bar([1], [1e3 * sV], color='gray', alpha=.5) #set_plot(AX1[0], ['left'], xticks=[], ylim=[0,11], yticks=[0, 5, 10], yticks_labels=['-65', '-60', '-55'], ylabel='mean (mV)') #set_plot(AX2[0], ['left'], xticks=[], ylim=[0,5], yticks=[0, 2, 4], ylabel='std. dev. (mV)') ### EXCITATORY CONDUCTANCE MEAN_GE, STD_GE, KYRT_GE = [], [], [] for i in range(len(Ge_exc)): MEAN_GE.append(Ge_exc[i][(time_array > min_time)].mean()) MEAN_GE.append(Ge_inh[i][(time_array > min_time)].mean()) STD_GE.append(Ge_exc[i][(time_array > min_time)].std()) STD_GE.append(Ge_inh[i][(time_array > min_time)].std()) AX1[1].bar([0], np.array(MEAN_GE).mean(), yerr=np.array(MEAN_GE).std(), color='w', edgecolor='g', lw=3, error_kw=dict(elinewidth=3, ecolor='g'), label='num. sim.') AX2[1].bar([0], np.array(STD_GE).mean(), yerr=np.array(STD_GE).std(), color='w', edgecolor='g', lw=3, error_kw=dict(elinewidth=3, ecolor='g'), label='exc.') AX1[1].bar([1], [1e9 * mGe], color='g', label='mean field \n pred.') AX2[1].bar([1], [1e9 * sGe], color='g', label='exc.') #set_plot(AX1[1], ['left'], xticks=[], yticks=[0,15,30], ylabel='mean (nS)') #set_plot(AX2[1], ['left'], xticks=[], yticks=[0,5,10], ylabel='std. dev. (nS)') ### INHIBITORY CONDUCTANCE MEAN_GI, STD_GI, KYRT_GI = [], [], [] for i in range(len(Gi_exc)): MEAN_GI.append(Gi_exc[i][(time_array > min_time)].mean()) MEAN_GI.append(Gi_inh[i][(time_array > min_time)].mean()) STD_GI.append(Gi_exc[i][(time_array > min_time)].std()) STD_GI.append(Gi_inh[i][(time_array > min_time)].std()) AX1[2].bar([0], np.array(MEAN_GI).mean(), yerr=np.array(MEAN_GI).std(), color='w', edgecolor='r', lw=3, error_kw=dict(elinewidth=3, ecolor='r'), label='num. sim.') AX2[2].bar([0], np.array(STD_GI).mean(), yerr=np.array(STD_GI).std(), color='w', edgecolor='r', lw=3, error_kw=dict(elinewidth=3, ecolor='r'), label='inh.') AX1[2].bar([1], [1e9 * mGi], color='r', label='mean field \n pred.') AX2[2].bar([1], [1e9 * sGi], color='r', label='inh.') #set_plot(AX1[2], ['left'], xticks=[], yticks=[0,15,30], ylabel='mean (nS)') #set_plot(AX2[2], ['left'], xticks=[], yticks=[0,5,10], ylabel='std. dev. (nS)') ### POPULATION RATE ### fig, ax = plt.subplots(figsize=(4, 3)) # we bin the population rate N0 = int(BIN / (time_array[1] - time_array[0])) N1 = int((time_array[cond_t][-1] - time_array[cond_t][0]) / BIN) time_array = time_array[cond_t][:N0 * N1].reshape((N1, N0)).mean(axis=1) rate_exc = rate_exc[cond_t][:N0 * N1].reshape((N1, N0)).mean(axis=1) rate_inh = rate_inh[cond_t][:N0 * N1].reshape((N1, N0)).mean(axis=1) rate_array = rate_array[cond_t][:N0 * N1].reshape((N1, N0)).mean(axis=1) hh, bb = np.histogram(rate_exc, bins=3, normed=True) ax.bar(.5 * (bb[:-1] + bb[1:]), hh, color='w', width=bb[1] - bb[0], edgecolor='g', lw=3, label='exc.', alpha=.7) hh, bb = np.histogram(rate_inh, bins=5, normed=True) ax.bar(.5 * (bb[:-1] + bb[1:]), hh, color='w', width=bb[1] - bb[0], edgecolor='r', lw=3, label='inh', alpha=.7) ax.fill_between(xfe, 0 * fe_pred, fe_pred, color='g', alpha=.8) ax.fill_between(xfi, 0 * fi_pred, fi_pred, color='r', alpha=.8) #set_plot(plt.gca(), ['bottom', 'left'], xlabel='pop. activity (Hz)', yticks=[], ylabel='density') for ax in AX1: ax.legend() for ax in AX2: ax.legend() return [fig, fig1, fig2]
import matplotlib.pylab as plt from scipy.optimize import fsolve from scipy.optimize import minimize import math NTWK = 'CONFIG1' NRN1 = 'HH_RS' NRN2 = 'HH_RS' TF1, TF2 = load_transfer_functions(NRN1, NRN2, NTWK) M = get_connectivity_and_synapses_matrix(NTWK, SI_units=True) params = get_neuron_params(NRN1, SI_units=True) reformat_syn_parameters(params, M) paramsinh = get_neuron_params(NRN2, SI_units=True) reformat_syn_parameters(paramsinh, M) Qe, Te, Ee = params['Qe'], params['Te'], params['Ee'] Qi, Ti, Ei = params['Qi'], params['Ti'], params['Ei'] Gl, Cm, El = params['Gl'], params['Cm'], params['El'] pconnec, Ntot, gei, ext_drive = params['pconnec'], params['Ntot'], params[ 'gei'], M[0, 0]['ext_drive'] N = 100 freqs = np.linspace(3, 7, N) frespthEx = 0 * freqs muVexcth = 0 * freqs stdexcth = 0 * freqs
def Euler_method_for_ring_model(NRN1, NRN2, NTWK, RING, STIM, BIN=5e-3,\ custom_ring_params={}, custom_stim_params={}): """ Given two afferent rate input excitatory and inhibitory respectively this function computes the prediction of a first order rate model (e.g. Wilson and Cowan in the 70s, or 1st order of El Boustani and Destexhe 2009) by implementing a simple Euler method IN A 2D GRID WITH LATERAL CONNECTIVITY the number of laterally connected units is 'connected_neighbors' there is an exponential decay of the strength 'decay_connect' ---------------------------------------------------------------- the core of the formalism is the transfer function, see Zerlaut et al. 2015 it can also be Kuhn et al. 2004 or Amit & Brunel 1997 ----------------------------------------------------------------- nu_0 is the starting value value of the recurrent network activity it should be the fixed point of the network dynamics ----------------------------------------------------------------- t is the discretization used to solve the euler method BIN is the initial sampling bin that should correspond to the markovian time scale where the formalism holds (~5ms) conduction_velocity=0e-3, in ms per pixel !!! """ print('----- loading parameters [...]') M = get_connectivity_and_synapses_matrix(NTWK, SI_units=True) ext_drive = M[0, 0]['ext_drive'] params = get_neuron_params(NRN2, SI_units=True) reformat_syn_parameters(params, M) afferent_exc_fraction = M[0, 0]['afferent_exc_fraction'] print('----- ## we look for the fixed point [...]') try: fe0, fi0, muV0 = np.load("fixed_point_data_TO_BE_REMOVED.npy") print( "/!\\ STORED FIXED POINT DATA LOADED, check if not a different config /!\\" ) except IOError: fe0, fi0 = find_fixed_point_first_order(NRN1, NRN2, NTWK, exc_aff=ext_drive) muV0, _, _, _ = get_fluct_regime_vars(fe0 + ext_drive, fi0, *pseq_params(params)) np.save('fixed_point_data_TO_BE_REMOVED.npy', [fe0, fi0, muV0]) print('----- ## we load the transfer functions [...]') TF1, TF2 = load_transfer_functions(NRN1, NRN2, NTWK) print('----- ## ring initialisation [...]') X, Xn_exc, Xn_inh, exc_connected_neighbors, exc_decay_connect, inh_connected_neighbors,\ inh_decay_connect, conduction_velocity = ring.pseq_ring_params(RING, custom=custom_ring_params) print('----- ## stimulation initialisation [...]') t, Fe_aff = stim.get_stimulation(X, STIM, custom=custom_stim_params) Fi_aff = 0 * Fe_aff # no afferent inhibition yet print('----- ## model initialisation [...]') Fe, Fi, muVn = 0 * Fe_aff + fe0, 0 * Fe_aff + fi0, 0 * Fe_aff + muV0 print('----- starting the temporal loop [...]') dt = t[1] - t[0] # constructing the Euler method for the activity rate for i_t in range(len(t) - 1): # loop over time for i_x in range(len(X)): # loop over pixels # afferent excitation + exc DRIVE fe = (1 - afferent_exc_fraction) * Fe_aff[ i_t, i_x] + ext_drive # common both to exc and inh fe_pure_exc = (2 * afferent_exc_fraction - 1) * Fe_aff[i_t, i_x] # only for excitatory pop fi = 0 # 0 for now.. ! # EXC --- we add the recurrent activity and the lateral interactions for i_xn in Xn_exc: # loop over neighboring excitatory pixels # calculus of the weight exc_weight = ring.gaussian_connectivity( i_xn, 0., exc_decay_connect) # then we have folded boundary conditions (else they donot # have all the same number of active neighbors !!) i_xC = (i_x + i_xn) % (len(X)) if i_t > int(abs(i_xn) / conduction_velocity / dt): it_delayed = i_t - int( abs(i_xn) / conduction_velocity / dt) else: it_delayed = 0 fe += exc_weight * Fe[it_delayed, i_xC] # INH --- we add the recurrent activity and the lateral interactions for i_xn in Xn_inh: # loop over neighboring inhibitory pixels # calculus of the weight inh_weight = ring.gaussian_connectivity( i_xn, 0., inh_decay_connect) # then we have folded boundary conditions (else they donot # have all the same number of active neighbors !!) i_xC = (i_x + i_xn) % (len(X)) if i_t > int(abs(i_xn) / conduction_velocity / dt): it_delayed = i_t - int( abs(i_xn) / conduction_velocity / dt) else: it_delayed = 0 fi += inh_weight * Fi[it_delayed, i_xC] ## NOTE THAT NO NEED TO SCALE : fi*= gei*pconnec*Ntot and fe *= (1-gei)*pconnec*Ntot ## THIS IS DONE IN THE TRANSFER FUNCTIONS !!!! # now we can guess the rate model output muVn[i_t + 1, i_x], _, _, _ = get_fluct_regime_vars(fe, fi, *pseq_params(params)) Fe[i_t + 1, i_x] = Fe[i_t, i_x] + dt / BIN * (TF1(fe + fe_pure_exc, fi) - Fe[i_t, i_x]) Fi[i_t + 1, i_x] = Fi[i_t, i_x] + dt / BIN * (TF2(fe, fi) - Fi[i_t, i_x]) print('----- temporal loop over !') return t, X, Fe_aff, Fe, Fi, np.abs((muVn - muV0) / muV0)